<template>
	<view class="template-reserve webview-template-reserve tn-safe-area-inset-bottom">
		<!-- 加载背景蒙版层 -->
		<view v-if="isFace" class="loading-overlay">
			<image src="/static/loading2.gif" class="loading-spinner"></image>
			<view style="font-size: 13px;font-weight: 500;">加载中...</view>
			<view style="font-size: 12px; margin-top: 5px;color: #ccc;">加载完成后，人物画质会在5秒内逐渐变清晰</view>
		</view>
		<view class="slideshow" @tap="togglePicker(0)" id="playerWrapper" v-if="isFace">
			<view class="slideshow-image" :style="'background-image: url(' +
				noFace +
				');background-size: cover;background-position: center;'
				">
			</view>
		</view>
		<text :prop="options" :change:prop="renderScript.onChange" v-show="false"></text>
		<text :prop="statusoptions" :change:prop="renderScript.checkConnectionStatus" v-show="false"></text>
		<text :prop="turnoptions" :change:prop="renderScript.getTurnCredentials" v-show="false"></text>
		<!-- 页面内容 -->
		<!-- <div class="section video-section" style="z-index: -999;" v-if="isFace"> -->
		<view class="video-container" id="video2">
			<video class="slideshow2" @play="videoPlay" @pause="videoPause" id="video_map" :controls="false"
				:custom-cache="false" autoplay></video>
			<view v-if="!isshowppt && !isshowproductppt">
				<view class="gradient-overlay bottom"></view>
			</view>
		</view>

		<!-- <cover-view
      :style="'position: fixed;z-index: 9996;bottom: 78.5%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!issayppt && ismyagent">
      <cover-image src="/static/backgroundimg.png" style="width: 88rpx;height: 18.5vh;opacity: 0.5;"></cover-image>
    </cover-view> -->

		<!-- <cover-view
      :style="'position: fixed;z-index: 9999;bottom: 91.5%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="isMeeting && !issayppt && ismyagent">
      <cover-image @click="endMeeting" src="/static/image/audiooff.png"
        style="width: 80rpx;height: 80rpx;"></cover-image>
    </cover-view>

    <cover-view
      :style="'position: fixed;z-index: 9999;bottom: 91.5%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!isMeeting && !issayppt && ismyagent">
      <cover-image @click="startMeeting" src="/static/image/audioon.png"
        style="width: 80rpx;height: 80rpx;"></cover-image>
    </cover-view>

    <cover-view
      :style="'position: fixed;z-index: 9999;bottom: 91%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!issayppt && ismyagent">
      <cover-image src="/static/image/line.png" style="width: 80rpx;height: 4rpx;"></cover-image>
    </cover-view>

    <cover-view
      :style="'position: fixed;z-index: 9999;bottom: 85.5%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!issayppt && ismyagent">
      <cover-image @click="showSchedule" src="/static/image/schedule.png"
        style="width: 80rpx;height: 80rpx;"></cover-image>
    </cover-view> -->
		<!-- 
    <cover-view
      :style="'position: fixed;z-index: 9999;bottom: 85%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!issayppt && ismyagent">
      <cover-image src="/static/image/line.png" style="width: 80rpx;height: 4rpx;"></cover-image>
    </cover-view> -->

		<!-- <cover-view
		:style="'position: fixed;z-index: 9999;bottom: 79.5%;left: 43%;width: 100%;display: flex;justify-content: center;'" v-if="!issayppt && ismyagent">
		<cover-image @click="showPptList" src="/static/PPT.png"
			style="width: 80rpx;height: 80rpx;"></cover-image>
	</cover-view> -->

		<!-- <cover-view
		:style="'position: fixed;z-index: 9999;bottom: 79.5%;left: 43%;width: 100%;display: flex;justify-content: center;'" v-if="!issayppt && ismyagent">
		<cover-image @click="goFrame" src="/static/Frame.png"
			style="width: 80rpx;height: 80rpx;"></cover-image>
	</cover-view> -->

		<!-- <cover-view
      :style="'position: fixed;z-index: 9999;bottom: 79.5%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!issayppt && ismyagent">
      <cover-image @click="goFoodLuck" src="/static/food-luck.png" style="width: 80rpx;height: 80rpx;"></cover-image>
    </cover-view> -->

		<cover-view
			:style="'position: fixed;z-index: 9999;bottom: 3%;left: 43%;width: 100%;display: flex;justify-content: center;opacity: 0.8;'"
			v-if="issayppt && ismyagent">
			<cover-image @click="closePptList" src="/static/image/clear.png"
				style="width: 60rpx; height: 60rpx"></cover-image>
		</cover-view>

		<!-- </div> -->
		<!-- <video class="slideshow" id="myvideo" autoplay playsinline controls></video> -->
		<!-- <web-view src="http://h5.cycyai.com:6502/webRTC.html" style="z-index: -999;" id="my-webview" ref="webview"></web-view> -->
		<!-- <view class="slideshow" @tap="togglePicker(0)" id="playerWrapper" v-if="isFace"> -->
		<!-- <view class="slideshow-image" :style="'background-image: url('+ noFace +')'"></view> -->
		<!-- </view> -->

		<!-- <cover-view
      :style="'position: fixed;z-index: 9996;bottom: 91%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!issayppt && !ismyagent">
      <cover-image src="/static/backgroundimg.png" style="width: 88rpx;height: 6vh;opacity: 0.5;"></cover-image>
    </cover-view> -->

		<!-- <cover-view
      :style="'position: fixed;z-index: 9999;bottom: 91.5%;left: 43%;width: 100%;display: flex;justify-content: center;'"
      v-if="!issayppt && !ismyagent">
      <cover-image @click="showPptList" src="/static/PPT.png" style="width: 80rpx;height: 80rpx;"></cover-image>
    </cover-view> -->

		<cover-view
			:style="'position: fixed;z-index: 9999;bottom: 3%;left: 43%;width: 100%;display: flex;justify-content: center;opacity: 0.8;'"
			v-if="issayppt && !ismyagent">
			<cover-image @click="closePptList" src="/static/image/clear.png"
				style="width: 60rpx; height: 60rpx"></cover-image>
		</cover-view>

		<view class="qsflex-container" style="
        position: absolute;
        z-index: 9999;
        bottom: 32vh;
        padding-left: 1%;
        padding-right: 1%;
        width: 100%;
        display: flex;
      " v-if="isShowBtn && !showSubscriptionMask && !isshowppt && !isshowproductppt">
			<!-- 循环生成元素 -->
			<view v-for="(item, index) in qslist" :key="index" class="qsflex-item tn-flex">
				<!-- 这里放你的内容，比如 <text>  background-color: rgba(255, 255, 255, 0.9);-->
				<text class="ctxt2" style="
            background-color: rgba(255, 255, 255, 0.9);
            color: #000;
            border-radius: 10px;
            padding: 10px;
            margin-bottom: 10px;
          " @click="showquery(item.content)">{{ item.content }}</text>
			</view>
		</view>
		<!-- PPT -->
		<swiper class="banner" :current="current" duration="600" disable-touch="true"
			indicator-color="rgba(255, 255, 255, 0.4)" indicator-active-color="#fff" v-if="isshowppt">
			<swiper-item v-for="(item, index) in bannerList" :key="index" class="swiper-item">
				<image class="banner-image" :src="item.url"></image>
				<!-- ================= 底部按住说话 ================= -->
				<view class="tn-footerfixed swiper-fixed custom-footer" id="msgbot">
					<view class="footer-main-text" @touchstart="handleRecordStart" @touchend="handleRecordEnd"
						@touchcancel="handleRecordEnd" @touchmove="handleRecordMove">
						<template v-if="!isRecording">
							<view class="recording-text" style="color: #000">按住讲话</view>
						</template>
						<template v-else>
							<view class="recording-bar-outer">
								<view class="recording-bar-inner">
									<view class="recording-bar" :class="{ animating: isRecording }">
										<view v-for="(n, idx) in 13" :key="idx" class="bar"
											:style="{ '--delay': idx * 0.1 + 's' }">
										</view>
									</view>
								</view>
							</view>
						</template>
					</view>
				</view>
			</swiper-item>
		</swiper>
		<!-- 讲产品 -->
		<swiper class="banner2" :current="current" duration="600" disable-touch="true"
			indicator-color="rgba(255, 255, 255, 0.4)" indicator-active-color="#fff" v-if="isshowproductppt">
			<swiper-item v-for="(item, index) in bannerList" :key="index" class="swiper-item">
				<image class="banner2-image" :src="item.url" mode="widthFix"></image>
			</swiper-item>
		</swiper>
		<!-- 日程弹窗 -->
		<collections-schedule :showDrawer.sync="showDrawer2" :isScheduleActive="isScheduleActive" :gender="userGender"
			:agent="zhushou || {}" :changeClothes="(scheduleData || []).filter((item) => item)"
			@clothesClick="handleClothesClick2" @update:isScheduleActive="onScheduleActiveUpdate" />
		<!-- 智能体详情弹窗 -->
		<collections-drawer :showDrawer.sync="showDrawer" :gender="userGender" :agent="zhushou || {}" />
		<!-- 换装弹窗 -->
		<change-clothes :showCDrawer.sync="showCDrawer" :isClothesActive="isClothesActive" :gender="userGender"
			:agent="zhushou || {}" :changeClothes="(headimgurlData || []).filter((item) => item && item.headimgurl)
				" @clothesClick="handleClothesClick" @update:isClothesActive="onClothesActiveUpdate" />
		<!-- 食神 -->
		<luck-food :showLuckFood.sync="showLuckFood" :foodLuckData="foodLuckData"
			@resetFoodLuckActive="resetFoodLuckActive" />
		<!-- 分享海报组件 -->
		<share-poster :show="isSharePosterVisible" :invite-code="inviteCode" @cancel="hideSharePoster"
			@share="handleShare" />
		<!-- 用户信息 -->
		<view class="header" style="z-index: 990" :style="{ paddingTop: 48 + 'px' }">
			<view class="top" @click.stop="openDrawer">
				<view class="user tn-flex" v-if="zhushou && !isshowppt">
					<image class="avatar tn-flex" :style="'background-image:url(' + zhushou.logourl + ');'"
						@click="showinfo()">
					</image>
					<view class="userinfo tn-flex" @click="showinfo()">
						<text class="username">{{ zhushou.title }}</text>
						<text class="company-name">{{ zhushou.company_name }}</text>
						<text style="font-size: 20rpx"></text>
					</view>
					<!-- <view class="follow tn-flex" v-if="zhushou.focus==0">
	           <text class="tn-icon-add-fill tn-padding-right-xs tn-color-white"
	            style="font-size: 50rpx;" @click="myfocus(zhushou.zsid,1)" v-if="zhushou.focus==0"></text>
	        </view>
			<view class="follow tn-flex" v-if="zhushou.focus==1">
			  <text class="tn-icon-reduce-circle-fill tn-padding-right-xs tn-color-white"
				style="font-size: 50rpx;" @click="myfocus(zhushou.zsid,0)" v-if="zhushou.focus==1"></text>
			</view> -->
				</view>
				<!-- <view class="search-icon">
	      <view class="custom-nav__search__icon tn-icon-search tn-color-white" @click="tn('/homePages/search')"></view>
	    </view> -->
			</view>
			<view class="intimacy-box" v-if="intimacy !== -1">
				<image :src="intimacyIcon" class="intimacy-item-icon"></image>
				<view class="intimacy-item-title">
					<text>亲密度</text>
					<text class="intimacy-item-value">{{ intimacy }}</text>
				</view>
			</view>
			<!-- 更多功能面板 -->
			<view class="more-content">
				<view class="more-item">
					<cover-view class="more-icon-bg">
						<cover-image src="/static/Album.png" @click.stop="selectImage" class="more-icon" />
					</cover-view>
					<cover-view class="more-text">相册</cover-view>
				</view>
				<view class="more-item">
					<cover-view class="more-icon-bg">
						<cover-image src="/static/Takephoto.png" @click.stop="takePhoto" class="more-icon" />
					</cover-view>
					<cover-view class="more-text">拍照</cover-view>
				</view>
			</view>
			<!-- <view class="title-list tn-flex"> -->
			<!-- <view class="title-item tn-flex">
	      <text class="tn-icon-relation tn-padding-right-xs tn-color-white"></text>
	      <text class="text">{{ zhushou.link_num }}链接</text>
	    </view> -->
			<!-- <view class="title-item tn-flex">
	      <text class="tn-icon-reply-fill tn-padding-right-xs tn-color-white"></text>
	      <text class="text">88888分享</text>
	    </view> -->
			<!-- </view> -->
		</view>

		<!-- <cover-view
		:style="'position: fixed;z-index: 9999;bottom: 88%;left: 43%;width: 100%;display: flex;justify-content: center;'" v-if="isMeeting">
		<cover-image @click="endMeeting" src="/static/image/audiooff.png"
			style="width: 50rpx;height: 50rpx;"></cover-image>
	</cover-view>
	
	<cover-view
		:style="'position: fixed;z-index: 9999;bottom: 88%;left: 43%;width: 100%;display: flex;justify-content: center;'" v-if="!isMeeting">
		<cover-image @click="startMeeting" src="/static/image/audioon.png"
			style="width: 50rpx;height: 50rpx;"></cover-image>
	</cover-view> -->

		<cover-view
			:style="'position: absolute;z-index: 9999;bottom: 93%;left: 43%;width: 100%;display: flex;justify-content: center;'"
			v-if="!isShowBtn">
			<cover-image @click="setShowBtn" src="/static/image/bs1.png"
				style="width: 50rpx; height: 50rpx"></cover-image>
		</cover-view>

		<!-- <svg style="position: absolute;" width="100%" height="100%" v-if="isVideo">
	    <defs>
	        <mask id="myMask">
	            <rect x="0" y="0" width="100%" height="100%" style="fill: #ffffff"></rect>
	            <circle cx="50%" cy="30%" r="27%" fill-opacity="1.0" style="fill: #000" />
	        </mask>
	    </defs>
	    <rect x="0" y="0" width="100%" height="100%" style="stroke: none; fill: #1c1d21; mask: url(#myMask)"></rect>
	</svg> -->
		<view class="reserve tn-safe-area-inset-bottom" :style="{ height: scrollHeight, margin: messageMargins }"
			@touchmove="handleScroll" style="z-index: 990" v-if="!issayppt">
			<view class="reserve-content tn-padding tn-color-black tn-text-lg" v-if="isShowMsg && isShowBtn">
				<!--内容-->
				<view class="scroll" :class="{ 'justify-end': !list.length }" :style="{ height: scrollHeight }"
					v-if="!issayproductppt">
					<scroll-view :scroll-into-view="scrollViewId" scroll-y style="height: 95%">
						<view class="item-space"></view>
						<view class="reserve-tips">本内容由AI生成</view>
						<!-- <view class="time">晚上 10:04</view> -->
						<view v-for="(item2, index2) in list" :key="index2">
							<!--撤销-->
							<!-- <view v-if="item.msgType == 'cancel'" class="cancel"> -->
							<!-- <text v-if="item.role == 'ask'" class="text">你撤回了一条消息</text> -->
							<!-- <text v-else class="text">成员 {{ item.role }} 撤回了一条消息</text> -->
							<!-- </view> -->
							<view class="item tn-flex" :class="[item2.role == '用户' ? 'right' : 'left']">
								<!--处理头像-->
								<!-- <view v-if="item.role == 'ask'" class="face">
          					<image src="/static/image/pos1.png" class="face"></image>
          				</view>
          				<view v-else class="face">
          					<image src="/static/image/pos1.png" class="face"></image>
          				</view> -->
								<!--文本-->
								<!-- <view @longpress="longPress(item)" class="content tn-flex">
									<view class="ctxt" v-html="parseTextContentToHtml(item2.content)"></view>
								</view> -->
								<view v-if="item2.type === 0" @longpress="longPress(item)" class="content tn-flex">
									<view class="ctxt" v-html="parseTextContentToHtml(item2.content)"></view>
								</view>
								<view class="message-image" v-if="item2.type === 1">
									<image :src="item2.content" class="image-content" mode="aspectFill"
										@click="previewImage(item2.content)" />
								</view>

								<!--图片-->
								<!-- <image v-if="item.msgType == 'image'" @longpress="longPress(item)" :src="item.content" mode="widthFix" style="width: 320upx;"></image> -->
								<!--地图-->
								<!-- <view v-if="item.msgType == 'map'" class="content map" @tap="openLocation(item.content)">
          					<view class="title">{{ item.content.address }}</view>
          					<map class="box"
          						:latitude="item.content.latitude" 
          						:longitude="item.content.longitude"
          						:markers="[{latitude: item.content.latitude, longitude: item.content.longitude, iconPath: '/static/img/marker.png'}]" 
          						@tap="openLocation(item.content)"
          					></map>
          				</view> -->
								<!--语音-->
								<!-- <view v-if="item.msgType == 'voice'" @tap="playVoice(item)" class="content">
          					<image v-show="voicePlayingId != item.id" src="/static/img/audio.png" class="voice-icon"></image>
          					<image v-show="voicePlayingId == item.id" src="/static/img/audio-play.gif" class="voice-icon"></image>
          				</view> -->
							</view>
						</view>
						<view class="item tn-flex" :class="['left']" v-if="isThink">
							<view @longpress="longPress(item)" class="content tn-flex">
								<view class="ctxt tn-flex">思考中……</view>
							</view>
						</view>
						<view id="bottom" style="height: 1px"></view>
					</scroll-view>
				</view>
			</view>
			<!-- <cover-view v-if="isVideo"
      	style="position: fixed;z-index: 9999;top: 50rpx;right: 50rpx;">
      	<video :src="`rtmp://dx11.haoleen.com/videocall/${id}`" style="width: 200rpx;position: fixed;z-index: 9999;height: 360rpx; top: 60rpx;right: 50rpx;" autoplay :show-play-btn="false" object-fit="fill"></video>
      </cover-view> -->
			<!-- <cover-view
	  	:style="'position: fixed;z-index: 9999;bottom: 50vh;padding-left: 1%;width: 98%;display: flex;justify-content: center;height: 65px;'">
	  	<text class="content tn-flex" style="font-size: 14px;width: 98%;height: 65px;justify-content: flex-start;margin-top: 10px;margin-left: 6%;color: #000;">你可以问我:</text>
	  </cover-view> -->

			<cover-view :style="'position: fixed;z-index: 9999;bottom: ' +
				bottomSize +
				'rpx;padding-left: 1%;width: 98%;display: flex;justify-content: center;height: 45px;'
				" v-if="!isShowMsg && !iszstalk">
				<cover-view class="tn-custom-nav-bar__back" style="
            width: 98%;
            background: #414b8c;
            background-color: rgba(65, 75, 140, 0.4);
            border-radius: 10px;
          ">
					<!-- <cover-image :src="msgimg" class="face" style="width: 70rpx;height: 70rpx;"></cover-image> -->
					<text class="content tn-flex" style="
              width: 98%;
              height: 45px;
              justify-content: flex-end;
              margin-top: 10px;
              margin-right: 6%;
              color: #ffffff;
            ">{{ msgtext }}</text>
				</cover-view>
				<!-- <cover-image @click="changev" src="/static/image/qhvv.png"
	  		style="width: 110rpx;height: 110rpx;margin-left: 120rpx;"></cover-image> -->
			</cover-view>
			<view
				class="tn-footerfixed tn-flex tn-flex-row-between tn-flex-col-center tn-safe-area-inset-bottom dd-glass"
				style="z-index: 9999" id="msgbot">
				<!-- ================= 底部操作区 ================= -->
				<view class="tn-footerfixed reserve-webview-bottom custom-footer">
					<!-- 左侧切换按钮 -->
					<view class="footer-btn left" @tap="toggleEdit(!isEdit)">
						<image v-if="isEdit" src="/static/jianpan.png" class="footer-icon" />
						<image v-else src="/static/yy-icon.png" class="footer-icon" />
					</view>
					<!-- 输入框或语音按钮 -->
					<view v-if="isEdit" class="footer-main-input-wrap">
						<input @focus="inputFocus" @blur="inputBlur" :cursor-spacing="12" type="text"
							:adjust-position="false" v-model="content" class="footer-main-input" id="messageInput"
							placeholder="请输入内容" placeholder-style="color: #d2d2d2;font-size: 31rpx;font-weight: 500;" />
					</view>
					<view v-else class="footer-main-text" @touchstart="handleRecordStart" @touchend="handleRecordEnd"
						@touchcancel="handleRecordEnd" @touchmove="handleRecordMove">
						<template v-if="!isRecording">
							<view style="color: #d2d2d2">按住讲话</view>
						</template>
						<template v-else>
							<view class="recording-bar-outer">
								<view class="recording-bar-inner">
									<view class="recording-bar" :class="{ animating: isRecording }">
										<view v-for="(n, idx) in 13" :key="idx" class="bar"
											:style="{ '--delay': idx * 0.1 + 's' }">
										</view>
									</view>
								</view>
							</view>
						</template>
					</view>
					<!-- 全屏按钮 -->
					<view class="footer-btn fullscreen">
						<image v-if="isEdit" src="/static/fs-icon.png" @tap="send" @touchend.prevent="send"
							class="footer-icon-add" />
						<image @click="showMsg(false)" v-if="isShowMsg" src="/static/shouqi.png" class="footer-icon" />
						<image @click="showMsg(true)" v-if="!isShowMsg" src="/static/zhankai.png" class="footer-icon" />
					</view>
				</view>
				<!--语音-->

				<!-- <view class="justify-content-item tn-flex-col-center tn-flex-row-center tn-text-center tn-padding-bottom" @click="openLocation">
          <view class="tn-bg-gray--light tn-padding-xs tn-margin-sm tn-color-black tn-round">
            <text class="tn-icon-location-fill" style="font-size: 50rpx;"></text>
          </view>
        </view> -->
			</view>
		</view>
		<!-- 添加订阅蒙版组件 -->
		<subscription-mask :show="showSubscriptionMask" @subscribe="handleSubscribe" @upgrade="handleUpgrade" />

		<!-- 测试按钮 -->
		<view class="top-right-icon-wrapper">
			<view class="top-right-icon" @click.stop="goReport">
				<image src="/static/report.png" style="width: 20px; height: 20px">
				</image>
			</view>
			<view class="top-right-icon" v-if="formPage !== 'home'" @click.stop="goHome">
				<image src="/static/home-icon.png" style="width: 39px; height: 39px">
				</image>
			</view>
			<view class="top-right-icon" @click="onShare">
				<image src="/static/shara.png" style="width: 39px;height: 39px;">
				</image>
			</view>
			<view class="top-right-icon" @click.stop="testClick">
				<image :src="isMenuVisible ? '/static/zk.png' : '/static/sq.png'" style="width: 39px; height: 39px"
					:class="{ 'icon-rotated': !isMenuVisible }">
				</image>
			</view>
			<!-- 测试点击 -->
		</view>
		<!-- 添加图片预览组件 -->
		<view class="image-preview" v-if="showImagePreview" @click="closeImagePreview">
			<image :src="previewImageUrl" class="preview-image" mode="aspectFit" />
		</view>

		<!-- 右侧功能菜单 -->
		<view class="right-menu-container" :class="{ 'menu-hidden': !isMenuVisible }">
			<view class="menu-item" v-if="isMeeting && !issayppt && ismyagent"
				:class="{ active: activeMenuItem === 'version' }" @click="endMeeting">
				<image src="/static/image/audiooff.png" style="width: 45px; height: 45px"></image>
			</view>
			<view class="menu-item" v-if="!isMeeting && !issayppt && ismyagent" @click="startMeeting">
				<image src="/static/image/audioon.png" style="width: 45px; height: 45px"></image>
			</view>
			<!-- <view class="menu-item" v-if="!issayppt && ismyagent">
        <image src="/static/image/line.png" style="width: 60rpx; height: 4rpx"></image>
      </view> -->
			<view class="menu-item" v-if="!issayppt && ismyagent" @click="showSchedule">
				<image :src="isScheduleActive ? '/static/image/schedule-n.png' : '/static/image/schedule.png'"
					style="width: 45px; height: 45px"></image>
			</view>
			<!-- <view class="menu-item" v-if="!issayppt && ismyagent">
        <image src="/static/image/line.png" style="width: 60rpx; height: 4rpx"></image>
      </view> -->
			<!-- ppt -->
			<view class="menu-item" v-if="(!issayppt && ismyagent) || (!issayppt && !ismyagent)" @click="showPptList">
				<image :src="isPptActive ? '/static/PPT-n.png' : '/static/PPT.png'" style="width: 45px; height: 45px">
				</image>
			</view>

			<!-- 讲产品 -->
			<view class="menu-item" v-if="(!issayppt && ismyagent) || (!issayppt && !ismyagent)"
				@click="showProductPptList">
				<image :src="isProductPptActive ? '/static/sayp-n.png' : '/static/sayp.png'"
					style="width: 45px; height: 45px">
				</image>
			</view>
			<!-- <view class="menu-item" v-if="!issayppt && ismyagent">
        <image src="/static/image/line.png" style="width: 60rpx; height: 4rpx"></image>
      </view> -->
			<!-- 换装 -->
			<view class="menu-item" v-if="(!issayppt && ismyagent) || (!issayppt && !ismyagent)"
				@click.stop="showCloDrawer">
				<image :src="isClothesActive ? '/static/change-clothes-n.png' : '/static/change-clothes.png'"
					style="width: 45px; height: 45px"></image>
			</view>
			<!-- <view class="menu-item" v-if="!issayppt && ismyagent">
        <image src="/static/image/line.png" style="width: 60rpx; height: 4rpx"></image>
      </view> -->
			<!-- 组局 -->
			<view class="menu-item" v-if="!issayppt && ismyagent" @click="goFrame">
				<image :src="isFrameActive ? '/static/Frame-n.png' : '/static/Frame.png'"
					style="width: 45px; height: 45px">
				</image>
			</view>
			<!-- <view class="menu-item" v-if="!issayppt && ismyagent">
        <image src="/static/image/line.png" style="width: 60rpx; height: 4rpx"></image>
      </view> -->
			<!-- 食运 -->
			<view class="menu-item" v-if="!issayppt && ismyagent" @click="goFoodLuck">
				<image :src="isFoodLuckActive ? '/static/food-louck-n.png' : '/static/food-louck.png'"
					style="width: 45px; height: 45px"></image>
			</view>
			<!-- 视频 -->
			<view class="menu-item" v-if="!issayppt && ismyagent || (!issayppt && !ismyagent)"
				@click="startLocalCamera">
				<image :src="isVideoActive ? '/static/video-play-n.png' : '/static/video-play.png'"
					style="width: 45px; height: 45px"></image>
			</view>
		</view>
		<!-- 本地摄像头视频 -->
		<view v-show="showLocalCamera" class="local-camera-container">
			<video id="localVideo" class="local-camera-video" autoplay playsinline x5-video-player-fullscreen="true"
				:controls="false" :custom-cache="false"></video>
			<!-- 摄像头控制按钮 -->
			<view class="camera-controls">
				<image src="/static/index/close-icon.png" @click="stopLocalCamera" class="control-icon"></image>
				<image src="/static/index/fz-icon.png" @click="switchCamera()" class="control-icon"></image>
			</view>
		</view>
		<!-- 🎤 录音动画遮罩层 -->
		<view v-show="isRecording && wasCameraActive" class="recording-mask">
			<!-- 背景模糊层 -->
			<view class="recording-mask-bg"></view>

			<!-- 中心动画区域 -->
			<view class="recording-animation-center">
				<!-- 声波扩散圈（3层） -->
				<view class="sound-wave wave-1"></view>
				<view class="sound-wave wave-2"></view>
				<view class="sound-wave wave-3"></view>
				<!-- 中心脉动圆 -->
				<view class="recording-pulse-circle"></view>
				<!-- 音频波形条 -->
				<view class="recording-waveform">
					<view v-for="n in 20" :key="n" class="wave-bar" :style="{ '--bar-delay': n * 0.05 + 's' }"></view>
				</view>
			</view>

			<!-- 提示文字 -->
			<view class="recording-tip-text">
				<text class="recording-status">🎙️ 正在录音</text>
			</view>
		</view>
	</view>
</template>

<script>
import template_page_mixin from "@/libs/mixin/template_page_mixin.js"
import emoji from "@/plugins/emoji.js"
import myVoice from "@/components/self-voice/index.vue"
import SubscriptionMask from "@/components/subscriptionMask/index.vue"
import SharePoster from "@/components/share_poster/index.vue"
// import NextCas from "@nextcas/sdk";
// import Record from "@nextcas/voice";
// import {RTCPlayer} from '@/common/rtcplayer.esm.js'
import CollectionsDrawer from "@/components/collections-drawer/index.vue"
import ChangeClothes from "@/components/change-clothes/index.vue"
import CollectionsSchedule from "@/components/collections-schedule/index.vue"
import LuckFood from "@/components/luck-food/index.vue"
const innerAudioContext = uni.createInnerAudioContext()
const recorderManager = uni.getRecorderManager()
// const player = new RTCPlayer()
var dataChannel = null
var audioElement = null
var videoElement = null
var isTransmitting = true

// 添加全局变量声明
let pc = null

var stompClient = null

// 添加全局变量用于重连
var reconnectAttempts = 0
var MAX_RECONNECT_ATTEMPTS = 50
var RECONNECT_DELAY = 3000 // 3 seconds

let mystopMessage = JSON.stringify({
	type: "stop",
})
// 摄像头视频流
var cameraVideoElement = null


export default {
	pageStyle: {
		softinputMode: "adjustPan",
	},
	name: "TemplateReserve",
	mixins: [template_page_mixin],
	components: {
		myVoice,
		CollectionsDrawer,
		SubscriptionMask,
		ChangeClothes,
		CollectionsSchedule,
		SharePoster,
		LuckFood
	},
	data() {
		return {
			// 图片预览相关
			showImagePreview: false,
			previewImageUrl: "",
			isIceRestarting: false,
			iceDisconnectedTimeout: null,
			keepAliveInterval: null,
			heartbeatInterval: null,
			// 本地摄像头相关
			showLocalCamera: false,
			isVideoActive: false,
			// 🆕 录音遮罩相关
			wasCameraActive: false, // 记录录音前摄像头是否开启
			localVideoRafId: null,
			localStream: null,
			currentFacingMode: 'user', // 'user' 前置摄像头, 'environment' 后置摄像头
			videoImage: "",
			groupList: [{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "/static/logo.png",
			},
			{
				src: "https://resource.tuniaokj.com/images/shop/cup1.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_4.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_3.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_1.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_2.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_3.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_4.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_1.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_2.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_3.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_4.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_3.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_1.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_2.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_3.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/shop/watch1.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_4.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_2.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_1.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_2.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_3.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_4.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_2.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_4.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_1.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_2.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_4.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/blogger_beibei.jpg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_1.jpeg",
			},
			{
				src: "https://resource.tuniaokj.com/images/blogger/avatar_3.jpeg",
			},
			],
			showDrawer: false,
			showDrawer2: false,
			userGender: "female",
			isRecording: false,
			barHeights: Array(13).fill(24),
			barAnimTimer: null,
			// 分享海报参数
			isSharePosterVisible: false,
			posterImage: "/static/shara720.png",
			showSubscriptionMask: false, // 订阅蒙版显示
			showCDrawer: false, // 是否显示换装弹窗
			showLuckFood: false, // 是否显示食神弹窗
			foodLuckData: null, // 食神数据
			startY: 0,
			emojis: [],
			isEdit: false,
			isFocus: false,
			showEmoji: false,
			showFile: false,
			showVoice: false,
			scrollHeight: "auto", // 内容区域高度
			statusBarHeight: 0, // 状态栏高度
			scrollViewId: "bottom", // 滚动到最底部
			voicePlayingId: "", // 正在播放的消息ID
			content: "",
			list: [],
			socketOpen: false,
			socketMsgQueue: [],
			fromUserId: 666,
			fromUserFace: "/static/logo.png",
			toUserId: "",
			toUserName: "聊天室",
			tokenInfo: "",
			nextCas: "",
			record: "",
			isVideo: false,
			recording: false,
			inited: false,
			speacking: false,
			loading: true,
			role: "LuXun",
			role_name: "童薇",
			role_desc: "高冷御姐，美女总裁。",
			voiceId: "zh_female_meilinvyou_moon_bigtts",
			showTimbre: "",
			session: "",
			intervalId: null,
			intervalId2: null,
			intervalId3: null,
			isSend: false,
			options: {},
			statusoptions: {},
			turnoptions: {},
			initializeoptions: {},
			loginToken: uni.getStorageSync("loginToken") || "",
			userInfo: uni.getStorageSync("userInfo") || null,
			zhushou: null,
			zsid: 0,
			userid: "",
			audiooff: true,
			noFace: "",
			isFace: true,
			alive: true,
			isShowMsg: true,
			isMsgnul: true,
			isVolume: true,
			msgtext: "",
			msgimg: "",
			abortController: null,
			bottomSize: 180,
			mydataChannel: null,
			appSecret: null,
			baseurl: [],
			apibaseurl: "https://human.cycyai.com:8881",
			isLocked: false,
			sendnumf: 0,
			clientid: 0,
			iszstalk: true,
			isSpeaking: false,
			audioContext: null,
			analyser: null,
			animationId: null,
			qslist: [],
			issay: false,
			isShowBtn: true,
			isMeeting: false,
			TurnDataUsername: "",
			TurnDataPassword: "",
			isChoosingMedia: false, // 标记是否正在选择媒体
			pageReallyHidden: false, // 标记页面是否真正隐藏
			isThink: false,
			keyBoardHeight: 0,
			scheduleData: [],
			headimgurlData: [], // 换装数据
			botid: "", // 对应智能体ID
			messageMargins: "53vh 0px 0px 0px",
			isVideoPlay: false,
			ismyagent: false,
			issaykcb: true,
			bannerList: [], // 初始化为空，后续接口获取
			bannerList2: [], // 初始化为空，后续接口获取
			current: 0,
			averagenum: 0,
			averagesum: [0, 0, 0, 0],
			isnextppt: false,
			isshowppt: false,
			issayppt: false,
			isstopppt: false,
			isnextproductppt: false,
			isshowproductppt: false,
			issayproductppt: false,
			isstopproductppt: false,
			pptList: [],
			productPptList: [],
			friendList: [],
			videostyle: null,
			msgbotstyle: null,
			isask: false,
			activeMenuItem: "version", // 用于跟踪当前选中的菜单项
			isMenuVisible: true, //控制菜单显示/隐藏状态
			useJavaScriptAnimation: false, //
			isHomeWeb: false,
			isIos: false,
			isScheduleActive: false, //跟踪日程按钮的激活状态
			isPptActive: false, // 跟踪幻灯片按钮的激活状态
			isProductPptActive: false, // 跟踪讲产品按钮的激活状态
			isClothesActive: false, // 跟踪换装按钮的激活状态
			isFrameActive: false, // 跟踪组局按钮的激活状态
			isFoodLuckActive: false, //跟踪食神按钮的激活状态
			isVideoActive: false, // 跟踪视频按钮的激活状态
			formPage: '', // 添加formPage属性
			inviteCode: "", // 邀请码
			intimacy: "", // 亲密度
			intimacystatus: "", // 亲密度状态
			isMore: false, // 是否展示更多按钮
			querytype: 0, //问题类型
			isPerformingIceRestart: false,
			askImgMsg: null,

		}
	},
	computed: {
		intimacyIcon() {
			const value = Number(this.intimacy);
			if (!isFinite(value) || value <= 0) return "/static/Intimacy0.png";
			if (value <= 20) return "/static/Intimacy20.png";
			if (value <= 40) return "/static/Intimacy40.png";
			if (value <= 60) return "/static/Intimacy60.png";
			if (value <= 80) return "/static/Intimacy80.png";
			return "/static/Intimacy100.png";
		}
	},
	onLoad(option) {
		let userInfo = uni.getStorageSync('userInfo');
		this.inviteCode = userInfo.invite_code || option.invite_code;
		uni.setPageMeta({
			pageStyle: {
				softinputMode: "adjustPan",
			},
		})

		// 监听重置食运按钮状态的事件
		document.addEventListener('resetFoodLuckActive', (event) => {
			if (event.detail.action === 'resetFoodLuckActive') {
				this.isFoodLuckActive = false;
			}
		});

		// 监听重置组局按钮状态的事件
		document.addEventListener('resetFrameActive', (event) => {
			if (event.detail.action === 'resetFrameActive') {
				this.isFrameActive = false;
			}
		});
		if (option) {
			this.isHomeWeb = option.formPage === "home" ? true : false
			this.formPage = option.formPage
			this.appSecret = option.appsecret
			this.userid = option.userid
			this.clientid = this.generateClientId()
			let formData = {
				appsecret: option.appsecret,
				clientid: this.clientid,
				userid: this.userid,
			}
			this.$Request
				.getApi("/bot/api/getappsecretinfo", formData)
				.then(async (res) => {
					if (res.status == 1) {
						this.zhushou = res.data
						this.botid = res.data.id
						this.role_name = res.data.title
						this.role_desc = res.data.uin
						this.voiceId = res.data.timbre_code
						this.showTimbre = res.data.prologue
						this.noFace = res.data.headimgurl
						// this.baseurl = res.data.baseurl;
						this.qslist = res.data.showqueryg
						this.intimacy = res.data.intimacy
						this.getMsgData()
						await this.getImgTree() // 拿到id后再调用换装接口
						// this.clientid = this.generateClientId();
						// for (let i = 0; i < this.baseurl.length; i++) {
						// if(!this.isLocked){

						// 检查智能体体验有效期
						let paramsData = {
							botid: this.botid,
							userid: this.userid,
						}
						this.$Request
							.getApi("/bot/api/agentccheckbotlink", paramsData)
							.then(async (res) => {
								this.ismyagent = res.data
								if (res && res.status === -1) {
									this.showSubscriptionMask = true
								} else {
									this.showSubscriptionMask = false
									//连接数字人
									let formData = {
										id: this.zhushou.id,
										clientid: this.clientid,
									}
									this.$Request
										.getApi("/bot/api/agentlink", formData)
										.then((res) => {
											if (res.status == 0) {
												// uni.showModal({
												//     showCancel: false,
												//     title: "暂无可用链路,请联系管理员！",
												//     content: res.message,
												// })
												return
											}
										})

									const response = await fetch(
										"https://human.cycyai.com:10804/idle-node", {
										method: "GET",
										headers: {
											"Content-Type": "application/json",
										},
									}
									)

									const result2 = await response.json()

									if (result2.url != "") {
										this.apibaseurl = result2.url + "/"
										try {
											let response2 = await fetch(
												this.apibaseurl + "imagehuman-unlock-client-id", {
												method: "POST",
												headers: {
													"Content-Type": "application/json",
												},
												body: JSON.stringify({
													client_id: this.clientid,
												}),
											}
											)

											const response = await fetch(
												this.apibaseurl + "imagehuman-lock-client-id", {
												method: "POST",
												headers: {
													"Content-Type": "application/json",
												},
												body: JSON.stringify({
													client_id: this.clientid,
												}),
											}
											)

											const result = await response.json()

											if (result.status === "success") {
												// this.isLocked = true;
												// this.apibaseurl = 'https://human.cycyai.com:8881'+this.baseurl[i];

												let formData2 = {
													id: this.zhushou.id,
													cid: this.clientid,
													baseurl: this.apibaseurl,
												}
												this.$Request
													.getApi("/bot/api/agentlinkping", formData2)
													.then((res) => { })

												let date2 = {
													client_id: this.clientid,
												}
												// let date2 = null;
												this.abortController = new AbortController()
												this.turnoptions = {
													myDate: date2,
													signal: this.abortController.signal,
													url: this.apibaseurl +
														"imagehuman-get-turn-credentials",
												}
												//h5向app传参，触发事件
												uni.webView.postMessage({
													data: {
														action: "clientid",
														data: this.clientid,
													},
												})
												//h5向app传参，触发事件
												uni.webView.postMessage({
													data: {
														action: "baseurl",
														data: i,
													},
												})
												// break;
											} else {
												// continue;
											}
										} catch (error) {
											// console.error("Error toggling lock:", error)
											// continue;
										}
									}
								}
							})
							.catch(() => {
								this.showSubscriptionMask = false
							})
					} else {
						// uni.showModal({
						//   showCancel: false,
						//   title: "无用户信息,请联系管理员！",
						//   content: res.message,
						// })
					}
				})
		}
		// this.fromUserId = this.userInfo.userid;
		// 初始化内容高度
		this.setScrollHeight()
		if (this.isHomeWeb) {
			let {
				system
			} = uni.getSystemInfoSync()
			this.isIos = system.indexOf("iOS") > -1
			// console.log('当前环境',system)
			// console.log('是否是ios',this.isIos)
			this.messageMargins = this.isIos ?
				"53vh 0rpx 0rpx 0rpx" :
				"53vh 0rpx 0rpx 0rpx"
		}

		// 初始化状态栏高度
		uni.getSystemInfo({
			success: (res) => {
				this.statusBarHeight = res.statusBarHeight
			},
		})

		// if (option) {
		// 	this.role_name = option.role_name;
		// 	this.role_desc = option.role_desc;
		// 	this.voiceId = option.timbre;
		// }

		const recorderManager = uni.getRecorderManager()
		recorderManager.onError((err) => {
			console.error("recorderManager：" + err)
			// 根据错误信息进行相应的处理
		})

		// 结束录音
		recorderManager.onStop(function async(res) {
			// date.path = res.tempFilePath  // 这个是录音文件的临时地址
			// date.time = timeLength.value    // 录音时长

			// 上传音频文件到服务器上
			uni.uploadFile({
				url: "https://ocr.luyanshidai.com:6501/api/core/user/upload", //仅为示例，非真实的接口地址
				filePath: res.tempFilePath, //  这个是录音文件的临时地址
				name: "file",
				formData: {
					user: "test",
				},
				success: (uploadFileRes) => {
					// // console.log("uploadFileRes" + uploadFileRes.data)
				},
			})
			// // console.log("recorder stop" + JSON.stringify(res))
			self.voicePath = res.tempFilePath
		})
		// this.recorderManager.onStop(res=>{
		// 	this.upload(res.tempFilePath)
		// })

		// 结束播放
		innerAudioContext.onEnded((res) => {
			this.voicePlayingId = ""
		})

		// 设置标题
		if (this.zhushou && this.zhushou.title) {
			uni.setNavigationBarTitle({
				title: this.zhushou.title,
			})
		}

		// 获取参数
		this.toUserId = option.toUserId
		this.toUserName = option.toUserName
		this.emojis = emoji

		// 获取消息记录
		this.getList()

		// 监听webSocket消息
		// this.$xbcim.onmessage(data=>{
		// 	// 只接受单聊消息
		// 	if(data.type != 'single') return

		// 	// 处理数据
		// 	data.id = data.extra.id
		// 	data.userFace = data.extra.userFace
		// 	this.list.push(data)
		this.initScrollBar();
		this.getFoodLuckData();
		// })
	},
	onShow(){
		let {
			system
		} = uni.getSystemInfoSync()
		this.isIos = system.indexOf("iOS") > -1
		// console.log(this.isIos)
	},
	onReady() {
		this.initScrollBar()
		this.intervalId = setInterval(() => {
			let formData2 = {
				id: this.zhushou.id,
				cid: this.clientid,
				baseurl: this.apibaseurl,
			}
			this.$Request
				.getApi("/bot/api/agentlinkping", formData2)
				.then((res) => { })
			const messageToSend = JSON.stringify({})
			dataChannel.send(messageToSend)
		}, 300000)

		this.intervalId3 = setInterval(() => {
			let formData3 = {
				id: this.zhushou.id,
				userid: this.userid,
			}
			this.$Request
				.getApi("/bot/api/scheduleagentclinkping", formData3)
				.then((res) => {
					if (res.status === 1) {
						this.sendppt(res.message)
					}
				})
		}, 40000)

		let that = this
		this.intervalId2 = setInterval(() => {
			if (this.bannerList.length > 0) {
				// 假设 videoElement 是你的 <video> 元素，并且它已经通过 srcObject 设置了 WebRTC 视频流
				const stream = audioElement.srcObject
				this.averagenum = 0
				// 使用函数检查是否有声音
				// 检查 stream 是否有效且包含音频轨道
				if (stream && stream.getAudioTracks().length > 0) {
					const audioContext = new AudioContext()
					const source = audioContext.createMediaStreamSource(stream)
					const analyser = audioContext.createAnalyser()

					// 验证节点连接
					source.connect(analyser)

					// // // console.log('处理链路状态:', {
					//   sourceConnected: source.context === audioContext,
					//   analyserConnected: analyser.numberOfInputs > 0
					// });

					// 实时打印数据
					const dataArray = new Uint8Array(analyser.fftSize)
					// that.averagesum = 0;
					setInterval(() => {
						analyser.getByteTimeDomainData(dataArray)
						// // // console.log('样本数据:', Array.from(dataArray.slice(0, 10)));
						// 计算平均音量（值域 0~128）
						let sum = 0
						for (let i = 0; i < dataArray.length; i++) {
							sum += Math.abs(dataArray[i] - 128) // 计算每个样本的绝对偏移
						}

						let average = sum / dataArray.length

						// 判定逻辑（带防抖）
						// // console.log('sum:',sum);
						// // console.log('dataArray:',dataArray.length);
						// // console.log('average:',average);
						if (this.averagenum < 4) {
							this.averagenum = ++this.averagenum // 通过改变current，自动切换
						} else {
							this.averagenum = 0
						}
						this.averagesum[this.averagenum] = average
						if (average > 2) {
							// 阈值需根据 AI 语音特性调整
							// // // console.log('检测到 AI 说话');
							this.isSpeaking = true
							//   if (!this.isSpeaking) {
							// 	  this.isSpeaking = true;
							// 	  // this.showVoice = false;
							// 	  // // console.log('检测到 AI 说话');
							// 	  // uni.webView.postMessage({
							// 	  // 	  data: {
							// 	  // 		  action: 'AI说话',
							// 	  // 	  }
							// 	  // });
							//   }
							// } else {
							//   if (this.isSpeaking) {
							//     this.isSpeaking = false;
							// 	// this.showVoice = true;
							//     // // console.log('检测到 AI 停止说话');
							// 	// uni.webView.postMessage({
							// 	// 	  data: {
							// 	// 		  action: 'AI未说话',
							// 	// 	  }
							// 	// });
							//   }
						} else {
							this.isSpeaking = false
							// // // console.log('检测到 AI 停止说话');
						}
					}, 2000)
					// // console.log('bannerList:',this.bannerList.length);
					if (!this.isask && this.issayppt) {
						if (this.isstopppt) {
							if (
								this.averagesum[0] +
								this.averagesum[1] +
								this.averagesum[2] +
								this.averagesum[3] >
								0
							) {
								// // console.log('检测到 AI 说话');
								this.isstopppt = false
							}
						} else {
							if (
								this.averagesum[0] +
								this.averagesum[1] +
								this.averagesum[2] +
								this.averagesum[3] >
								0
							) {
								// // console.log('检测到 AI 说话');
								this.isnextppt = true
							} else {
								// // console.log('检测到 AI 停止说话');
								if (this.isnextppt) {
									if (this.current < this.bannerList.length) {
										this.isshowppt = true
										this.issayppt = true

										// var humanvideo = document.getElementById('video2');
										// humanvideo.style = this.videostyle;
										// humanvideo.style.width = `117px`;
										// humanvideo.style.height = `182px`;
										// humanvideo.style.transform = `rotate(90deg)`;
										// humanvideo.style.left = `25%`;
										// humanvideo.style.top = `81vh`;

										// var humanmsgbot = document.getElementById('msgbot');
										// humanmsgbot.style = this.msgbotstyle;
										// humanmsgbot.style.width = `168px`;
										// humanmsgbot.style.height = `44px`;
										// humanmsgbot.style.transform = `rotate(90deg)`;
										// humanmsgbot.style.left = `-0.5%`;
										// humanmsgbot.style.top = `-8vh`;
										// humanmsgbot.style.opacity = `0.7`;

										this.current = this.current + 1
										if (this.current == 0) {
											this.current = 1
										}
										this.sendppt(this.bannerList[this.current].title)
									} else {
										this.isshowppt = false
										this.bannerList = []
										this.current = 0

										this.issayppt = false
										isTransmitting = false
										dataChannel.send(mystopMessage)
										var humanvideo = document.getElementById("video2")
										humanvideo.style = this.videostyle
										var humanmsgbot = document.getElementById("msgbot")
										humanmsgbot.style = this.msgbotstyle
										humanmsgbot.style.padding = `0 0 0 2%`
										humanmsgbot.style.opacity = `0.6`
										// this.current = 0
										// this.bannerList = [];
									}
								}
								this.isnextppt = false
							}
						}
					}

					if (!this.isask && this.issayproductppt) {
						if (this.isstopproductppt) {
							if (
								this.averagesum[0] +
								this.averagesum[1] +
								this.averagesum[2] +
								this.averagesum[3] >
								0
							) {
								// // console.log('检测到 AI 说话');
								this.isstopproductppt = false
							}
						} else {
							if (
								this.averagesum[0] +
								this.averagesum[1] +
								this.averagesum[2] +
								this.averagesum[3] >
								0
							) {
								// // console.log('检测到 AI 说话');
								this.isnextproductppt = true
							} else {
								// // console.log('检测到 AI 停止说话');
								if (this.isnextproductppt) {
									if (this.current < this.bannerList.length) {
										this.isshowproductppt = true
										this.issayproductppt = true

										// var humanvideo = document.getElementById('video2');
										// humanvideo.style = this.videostyle;
										// humanvideo.style.width = `117px`;
										// humanvideo.style.height = `182px`;
										// humanvideo.style.transform = `rotate(90deg)`;
										// humanvideo.style.left = `25%`;
										// humanvideo.style.top = `81vh`;

										// var humanmsgbot = document.getElementById('msgbot');
										// humanmsgbot.style = this.msgbotstyle;
										// humanmsgbot.style.width = `168px`;
										// humanmsgbot.style.height = `44px`;
										// humanmsgbot.style.transform = `rotate(90deg)`;
										// humanmsgbot.style.left = `-0.5%`;
										// humanmsgbot.style.top = `-8vh`;
										// humanmsgbot.style.opacity = `0.7`;

										this.current = this.current + 1
										if (this.current == 0) {
											this.current = 1
										}
										this.sendppt(this.bannerList[this.current].title)
									} else {
										this.isshowproductppt = false
										this.bannerList = []
										this.current = 0

										this.issayproductppt = false
										isTransmitting = false
										dataChannel.send(mystopMessage)
										// this.current = 0
										// this.bannerList = [];
									}
								}
								this.isnextproductppt = false
							}
						}
					}
				}
			}
		}, 4000)
	},
	mounted() {
		var that = this
		document.addEventListener(
			"message",
			(e) => {
				//webview接收uniapp传过来的信息
				// // console.log("message", e.detail.ask)
				// // console.log(JSON.stringify(e.detail))
				if (e.detail.ask) {
					// console.log("message", e.detail.ask)
					// 执行截图功能
					if (e.detail.ask === '截图' || ['截图'].includes(e.detail.ask)) {
						that.capturePhoto()
						return
					}
					isTransmitting = false
					dataChannel.send(mystopMessage)
					// that.ask(e.detail.ask)
					that.content = e.detail.ask
					that.send()
				}
				if (e.detail.onhide) {
					isTransmitting = false
					dataChannel.send(mystopMessage)
				}
				if (e.detail.action === "keyboardHeight") {
					that.setScrollHeight(e.detail.data)
				}
				// 载体页面发送消息监听，调用消息查询
				if (e.detail.messageType === 'getMsgData') {
					that.sendImageMessage()
				}
				
				if (e.detail.messageImg) {
					that.askImgMsg = e.detail.messageImg;
					that.sendImageMessage()
				}
				if (e.detail.closeType) {
					setTimeout(() => {
						that.restoreMediaStreams()
					}, 200)
				}
				// if(e.detail.zsid){
				// 	this.getMsgData(e.detail.zsid);
				// }
				// this.ask(e.detail.ask)
			},
			false
		)
		// 检测CSS动画支持
		this.checkCSSAnimationSupport()
	},

	onHide() {
		var that = this;

		// ✅ 关键：如果是选择媒体或相机操作，完全跳过所有清理
		if (this.isChoosingMedia) {
			// console.log('⚠️ 临时操作（选择图片/相机），完全保持 WebRTC 连接');
			// 不执行任何清理操作
			return;
		}
		// ✅ 添加延迟检查，避免误触发
		setTimeout(() => {
			this.pageReallyHidden = true
			that.onAppBackground();

			// 页面隐藏时清除间隔调用
			if (that.intervalId) {
				clearInterval(that.intervalId);
			}
		}, 500); // 延迟500ms，给 isChoosingMedia 设置时间
	},
	onUnload() {
		var that = this
		if (this.intervalId) {
			clearInterval(this.intervalId)
		}
		if (this.intervalId2) {
			clearInterval(this.intervalId2)
		}
		if (this.intervalId3) {
			clearInterval(this.intervalId3)
		}
		// // console.log(this.session)
		let date = {
			session: this.session,
		}
		try {
			const response = fetch(this.apibaseurl + "imagehuman-unlock-client-id", {
				method: "POST",
				headers: {
					"Content-Type": "application/json",
				},
				body: JSON.stringify({
					client_id: this.clientid,
				}),
			})
			const response2 = fetch(that.apibaseurl + "/imagehuman-kill", {
				method: "POST",
				headers: {
					"Content-Type": "application/json",
				},
			})

			//   if (response.ok) {
			// 	// console.log('Server termination initiated');
			//   } else {
			// 	console.error('Failed to terminate server');
			//   }
		} catch (error) {
			console.error("Error terminating server:", error)
		}
		// this.$Request.postT("/api/core/user/lpostop",date).then((res) => {
		// 	// console.log(res);
		// 	player.stop();
		// 	this.session = null;
		// });
	},
	beforeDestroy() {
		// 释放资源
		if (this.audioContext) this.audioContext.close()
		if (this.animationId) cancelAnimationFrame(this.animationId)
		// 清理本地摄像头资源
		this.stopLocalCamera();
	},
	onBackPress() {
		if (this.showFile || this.showEmoji) {
			this.bottomSize = 180;
			this.showFile = false;
			this.showEmoji = false;
			this.setScrollHeight(0);
			return true;
		}
		return false;
	},
	methods: {
		// 获取食神数据
		getFoodLuckData() {
			this.$Request.postApi("/bot/api/agentcgetmyfoodluck", {
				userid: this.userid
			}).then(res => {
				if (res.status === 1 && res.data) {
					this.foodLuckData = res.data;
				}
			}).catch(err => {
				console.error('获取食神数据失败', err);
			});
		},
		async cleanupWebRTC() {
			try {
				// 停止心跳和保活
				if (this.heartbeatInterval) {
					clearInterval(this.heartbeatInterval);
					this.heartbeatInterval = null;
				}

				if (this.keepAliveInterval) {
					clearInterval(this.keepAliveInterval);
					this.keepAliveInterval = null;
				}

				// 关闭DataChannel
				if (dataChannel) {
					dataChannel.close();
					dataChannel = null;
				}

				this.mydataChannel = null;

				// 关闭PeerConnection
				if (pc) {
					// 移除所有事件监听器
					pc.onconnectionstatechange = null;
					pc.oniceconnectionstatechange = null;
					pc.ontrack = null;
					pc.onicecandidate = null;
					pc.onnegotiationneeded = null;
					pc.onerror = null;

					// 关闭所有transceivers
					pc.getTransceivers().forEach(transceiver => {
						if (transceiver.stop) {
							transceiver.stop();
						}
					});

					// 关闭发送器
					pc.getSenders().forEach(sender => {
						if (sender.track) {
							sender.track.stop();
						}
					});

					// 关闭连接
					pc.close();
					pc = null;
				}

				// 清理媒体元素
				const videoElement = document.getElementById("video_map")?.querySelector("video");
				const audioElement = document.querySelector('audio');

				if (videoElement && videoElement.srcObject) {
					videoElement.srcObject.getTracks().forEach(track => track.stop());
					videoElement.srcObject = null;
				}

				if (audioElement && audioElement.srcObject) {
					audioElement.srcObject.getTracks().forEach(track => track.stop());
					audioElement.srcObject = null;
				}

				// console.log('WebRTC资源清理完成');
			} catch (error) {
				console.error('清理WebRTC资源失败:', error);
			}
		},
		// ✅ 添加连接检查和恢复方法
		// ✅ 修改：只使用 ICE restart，不重新建立连接
		async checkAndRestoreConnection() {
			// console.log('检查 WebRTC 连接状态');

			if (!pc) {
				// console.log('WebRTC 连接不存在，无法恢复');
				uni.showToast({
					title: '连接已断开，请重新进入',
					icon: 'none'
				});
				return;
			}

			// 检查连接状态
			const connectionState = pc.connectionState;
			const iceConnectionState = pc.iceConnectionState;
			// ✅ 只在连接中断时尝试恢复，不重新建立
			if (connectionState === 'closed') {
				// console.log('连接已关闭，无法恢复');
				uni.showToast({
					title: '连接已关闭，请重新进入',
					icon: 'none'
				});
				return;
			}
			if (connectionState === 'connected' &&
				(iceConnectionState === 'connected' || iceConnectionState === 'completed')) {
				// console.log('✅ 连接状态正常，无需恢复');
				setTimeout(() => {
					// console.log(connectionState)
					// console.log('执行恢复视频流')
					this.restoreMediaStreams()
				}, 200)
				return; // 连接正常，直接返回，不执行 ICE restart
			}
			if (connectionState === 'disconnected' || connectionState === 'failed' ||
				iceConnectionState === 'disconnected' || iceConnectionState === 'failed') {
				// console.log('⚠️ 连接异常，尝试恢复...');
				const success = await this.tryIceRestartWithRetry(3);

				if (success) {
					// console.log('连接已成功恢复');
				} else {
					uni.showToast({
						title: '连接恢复失败，请重新进入',
						icon: 'none'
					});
				}
			} else {
				// console.log('连接状态:', connectionState, '/', iceConnectionState, '- 保持观察');
			}
		},
		// ✅ 新增：带重试机制的 ICE restart
		async tryIceRestartWithRetry(maxRetries = 3) {
			// console.log(`开始 ICE 重启，最多重试 ${maxRetries} 次`);

			for (let i = 0; i < maxRetries; i++) {
				// console.log(`ICE 重启尝试 ${i + 1}/${maxRetries}`);

				const success = await this.tryIceRestart();

				if (success) {
					// console.log('ICE 重启成功');
					return true;
				}

				// 如果不是最后一次，等待后重试
				if (i < maxRetries - 1) {
					const waitTime = 2000 * (i + 1); // 递增等待时间：2s, 4s, 6s
					// console.log(`等待 ${waitTime}ms 后重试`);
					await new Promise(resolve => setTimeout(resolve, waitTime));
				}
			}

			// console.log('所有 ICE 重启尝试均失败');
			return false;
		},
		async tryIceRestart() {
			if (!pc) {
				// console.log('无法进行ICE重启：pc不存在');
				return false;
			}

			if (this.isIceRestarting || this.isPerformingIceRestart) {
				// console.log('ICE重启正在进行中，跳过');
				return false;
			}

			try {
				this.isIceRestarting = true;
				this.isPerformingIceRestart = true; // 设置全局标记
				// console.log('开始ICE重启...');
				// console.log('当前连接状态:', pc.connectionState, '/', pc.iceConnectionState);

				// 检查当前连接状态
				if (pc.connectionState === 'closed') {
					// console.log('连接已关闭，无法重启');
					return false;
				}

				// ✅ 保存当前的 dataChannel 状态
				const dataChannelWasOpen = this.mydataChannel && this.mydataChannel.readyState === 'open';
				// console.log('DataChannel 状态:', dataChannelWasOpen ? 'open' : 'closed/null');

				// 创建新的 offer，带 iceRestart 选项
				// console.log('创建 ICE restart offer...');
				const offer = await pc.createOffer({
					iceRestart: true
				});
				await pc.setLocalDescription(offer);

				// console.log('发送 ICE restart offer 到服务器');

				// 发送新的 offer 到服务器
				const response = await fetch(this.apibaseurl + 'imagehuman-webrtc-offer', {
					method: "POST",
					body: JSON.stringify({
						sdp: pc.localDescription.sdp,
						type: pc.localDescription.type,
						client_id: this.clientid,
						image_id: this.zhushou.app_key,
						ice_restart: true // 标记这是 ICE 重启
					}),
					headers: {
						"Content-Type": "application/json",
					},
					// ✅ 添加超时
					signal: AbortSignal.timeout(10000) // 10秒超时
				});

				if (!response.ok) {
					const errorText = await response.text();
					throw new Error(`ICE重启请求失败: ${response.status} - ${errorText}`);
				}

				const answer = await response.json();
				// console.log('收到服务器 answer，设置远程描述');
				await pc.setRemoteDescription(new RTCSessionDescription(answer));

				// console.log('ICE重启协商完成，等待连接恢复...');

				// ✅ 等待连接恢复，增加超时时间
				const success = await this.waitForConnection(15000); // 等待15秒

				if (success) {
					// console.log('✅ ICE重启成功，连接已恢复');
					return true;
				} else {
					// console.log('❌ ICE重启超时或失败');
					return false;
				}
			} catch (error) {
				console.error('❌ ICE重启异常:', error);
				return false;
			} finally {
				// ✅ 延迟重置标记，避免并发问题
				setTimeout(() => {
					this.isIceRestarting = false;
					this.isPerformingIceRestart = false;
					// console.log('ICE重启标记已重置');
				}, 1000);
			}
		},
		waitForConnection(timeout = 15000) {
			return new Promise((resolve) => {
				const startTime = Date.now();
				let checkCount = 0;

				const checkConnection = () => {
					if (!pc) {
						// console.log('pc 不存在，连接失败');
						resolve(false);
						return;
					}

					checkCount++;
					const state = pc.iceConnectionState;
					const connState = pc.connectionState;
					const elapsed = Date.now() - startTime;

					// console.log(`[检查 ${checkCount}] ICE: ${state}, Conn: ${connState}, 已等待: ${elapsed}ms`);

					// ✅ 成功状态
					if (state === 'connected' || state === 'completed') {
						// console.log('✅ 连接已恢复');
						resolve(true);
						return;
					}

					// ✅ 失败状态
					if (state === 'closed') {
						// console.log('❌ 连接已关闭');
						resolve(false);
						return;
					}

					// ✅ 超时
					if (elapsed > timeout) {
						// console.log(`❌ 连接恢复超时 (${timeout}ms)`);
						resolve(false);
						return;
					}

					// ✅ 继续等待
					setTimeout(checkConnection, 500);
				};

				checkConnection();
			});
		},
		// 预览图片
		previewImage(imageUrl) {
			this.previewImageUrl = imageUrl;
			this.showImagePreview = true;
		},

		// 关闭图片预览
		closeImagePreview() {
			this.showImagePreview = false;
		},
		// 启动本地摄像头
		async startLocalCamera() {
			if (this.isVideoActive || this.showLocalCamera) {
				return
			}
			try {
				// 检查浏览器是否支持摄像头
				if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
					uni.showToast({
						title: '设备不支持摄像头',
						icon: 'none'
					});
					return;
				}

				// 请求摄像头权限
				const constraints = {
					video: {
						facingMode: this.currentFacingMode,
						width: {
							ideal: 1920
						},
						height: {
							ideal: 1080
						},
					},
					audio: false
				};
				this.localStream = await navigator.mediaDevices.getUserMedia(constraints);

				// 显示摄像头界面
				this.showLocalCamera = true;
				this.isVideoActive = true;

				// 等待DOM更新后绑定视频流
				this.$nextTick(async () => {
					cameraVideoElement = document.getElementById('localVideo').querySelector('video');
					if (cameraVideoElement) {
						cameraVideoElement.srcObject = this.localStream;
						try {
							await cameraVideoElement.play();
							// console.log('本地摄像头视频流已成功播放');

							// ✅ 添加保活机制：定期检查视频是否暂停
							const keepVideoAlive = () => {
								if (cameraVideoElement && cameraVideoElement.paused && this
									.showLocalCamera) {
									// console.log('检测到视频暂停，尝试恢复播放');
									cameraVideoElement.play().catch(e => console.error('恢复播放失败:',
										e));
								}
								if (this.showLocalCamera) {
									this.localVideoRafId = requestAnimationFrame(keepVideoAlive);
								}
							};
							this.localVideoRafId = requestAnimationFrame(keepVideoAlive);

						} catch (e) {
							console.error('视频播放失败:', e);
						}
					}
				});
			} catch (error) {
				console.error('启动摄像头失败:', error);
				let errorMessage = '启动摄像头失败';

				if (error.name === 'NotAllowedError') {
					errorMessage = '请允许访问摄像头权限';
				} else if (error.name === 'NotFoundError') {
					errorMessage = '未找到摄像头设备';
				} else if (error.name === 'NotReadableError') {
					errorMessage = '摄像头被其他应用占用';
					uni.showModal({
						title: '提示',
						content: '请检查摄像头权限或重启设备',
						success: () => uni.openSetting() // 跳转系统设置
					});
				}

				uni.showToast({
					title: errorMessage,
					icon: 'none'
				});
			}
		},

		// 切换前后摄像头
		async switchCamera(mode) {
			try {
				if (!this.localStream) {
					return;
				}

				// 停止当前流
				this.localStream.getTracks().forEach(track => {
					track.stop();
				});
				if (mode) {
					this.currentFacingMode = mode;
				} else {
					// 切换摄像头方向
					this.currentFacingMode = this.currentFacingMode === 'user' ? 'environment' : 'user';
				}
				// 重新获取摄像头流
				const constraints = {
					video: {
						facingMode: this.currentFacingMode,
						width: {
							ideal: 1920
						},
						height: {
							ideal: 1080
						},
					},
					audio: false
				};
				const stream = await navigator.mediaDevices.getUserMedia(constraints);
				this.localStream = stream

				// 更新视频元素
				if (cameraVideoElement) {
					cameraVideoElement.srcObject = stream;
				}
			} catch (error) {
				console.error('切换摄像头失败:', error);
				uni.showToast({
					title: '切换摄像头失败',
					icon: 'none'
				});

				// 如果切换失败，尝试恢复到原来的摄像头
				this.currentFacingMode = this.currentFacingMode === 'user' ? 'environment' : 'user';
			}
		},

		// 停止本地摄像头
		stopLocalCamera() {
			try {
				// ✅ 清除保活机制
				if (this.localVideoRafId) {
					cancelAnimationFrame(this.localVideoRafId);
					this.localVideoRafId = null;
				}

				if (this.localStream) {
					this.localStream.getTracks().forEach(track => {
						track.stop();
					});
					this.localStream = null;
				}

				if (cameraVideoElement) {
					cameraVideoElement.srcObject = null;
					cameraVideoElement = null;
				}

				this.showLocalCamera = false;
				this.isVideoActive = false;

			} catch (error) {
				console.error('关闭摄像头失败:', error);
			}
		},

		// 截图功能
		capturePhoto() {
			if (!cameraVideoElement) {
				uni.showToast({
					title: '摄像头未启动',
					icon: 'none'
				});
				return;
			}

			try {
				// 创建canvas来截图
				const canvas = document.createElement('canvas');
				const ctx = canvas.getContext('2d');

				canvas.width = cameraVideoElement.videoWidth;
				canvas.height = cameraVideoElement.videoHeight;

				ctx.drawImage(cameraVideoElement, 0, 0);

				// 转换为base64
				const imageData = canvas.toDataURL('image/jpeg', 0.8);

				// 这里可以处理截图数据，比如保存或上传
				// // console.log('截图成功:', imageData);

				uni.showToast({
					title: '截图成功',
					icon: 'success'
				});
				this.videoImage = imageData
				return imageData;

			} catch (error) {
				console.error('截图失败:', error);
				uni.showToast({
					title: '截图失败',
					icon: 'none'
				});
			}
		},
		// 弹起更多
		messageMore() {
			this.isMore = !this.isMore
		},
		goReport() {
			uni.webView.postMessage({
				data: {
					action: "举报",
				},
			})
		},
		goHome() {
			uni.webView.postMessage({
				data: {
					action: "首页",
				},
			})
		},
		goMy() {
			uni.webView.postMessage({
				data: {
					action: "我的",
				},
			})
		},

		handleShare() {
			uni.webView.postMessage({
				data: {
					action: "sharePoster",
					data: this.inviteCode
				},
			})
		},

		hideSharePoster() {
			// 恢复视频播放
			if (videoElement && videoElement.play) {
				videoElement.play()
			}
			// 恢复音频播放
			if (audioElement && audioElement.play) {
				audioElement.play()
			}

			// 如果有WebRTC音频轨道，也恢复它们
			if (audioElement && audioElement.srcObject) {
				const stream = audioElement.srcObject
				if (stream && stream.getAudioTracks().length > 0) {
					const audioTracks = stream.getAudioTracks()
					audioTracks.forEach((track) => {
						track.enabled = true // 启用音频轨道
					})
				}
			}
			this.isSharePosterVisible = false
		},
		// 暂停当前视频
		pauseVideoPlayback() {
			// 暂停当前视频
			if (videoElement && videoElement.pause) {
				videoElement.pause()
			}
			// 暂停音频
			if (audioElement && audioElement.pause) {
				audioElement.pause()
			}

			// 如果有WebRTC音频轨道，也暂停它们
			if (audioElement && audioElement.srcObject) {
				const stream = audioElement.srcObject
				if (stream && stream.getAudioTracks().length > 0) {
					const audioTracks = stream.getAudioTracks()
					audioTracks.forEach((track) => {
						track.enabled = false // 禁用音频轨道
					})
				}
			}
		},

		// 选择图片
		selectImage() {
			this.showMsg(true)
			dataChannel.send(mystopMessage)
			uni.webView.postMessage({
				data: {
					action: "selectImage",
				},
			})
			// 预留方案，别删除代码，目前注释
			// this.checkAndRestoreConnection()
		},
		// 拍照
		takePhoto() {
			this.showMsg(true)
			dataChannel.send(mystopMessage)
			uni.webView.postMessage({
				data: {
					action: "takePhoto",
				},
			})
			// 预留方案，别删除代码，目前注释
			// this.checkAndRestoreConnection()
		},
		// 分享海报
		onShare() {
			this.pauseVideoPlayback()
			this.isSharePosterVisible = true
		},
		// 右上角图标点击处理
		// handleTopRightIconClick() {
		//   // console.log("右上角图标被点击了，当前状态:", this.isMenuVisible);
		//   this.isMenuVisible = !this.isMenuVisible;
		//   // console.log("切换后状态:", this.isMenuVisible);
		// },

		// 测试点击方法
		testClick() {
			this.isMenuVisible = !this.isMenuVisible
		},
		goFrame() {
			this.isScheduleActive = false // 重置日程按钮状态
			this.isPptActive = false // 重置幻灯片按钮状态
			this.isProductPptActive = false
			this.isClothesActive = false // 重置换装按钮状态
			this.isFrameActive = true // 激活组局按钮
			this.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态
			this.closeProductPptList()
			uni.webView.postMessage({
				data: {
					action: "组局",
				},
			})
		},
		goFoodLuck() {
			this.isScheduleActive = false // 重置日程按钮状态
			this.isPptActive = false // 重置幻灯片按钮状态
			this.isProductPptActive = false
			this.isClothesActive = false // 重置换装按钮状态
			this.isFrameActive = false // 重置组局按钮状态
			this.isFoodLuckActive = true // 激活食神按钮
			this.isVideoActive = false // 重置视频按钮状态
			this.showLuckFood = true // 显示食神弹窗

			// 获取食神数据
			this.getFoodLuckData();
			this.closeProductPptList()
			// uni.webView.postMessage({
			// 	data: {
			// 		action: "食神",
			// 	},
			// })
		},
		// 重置食神按钮状态
		resetFoodLuckActive() {
			this.isFoodLuckActive = false;
		},
		videoPlay() {
			this.isVideoPlay = true
		},
		videoPause() {
			this.isVideoPlay = false
		},
		showSchedule() {
			this.isScheduleActive = true // 激活日程按钮
			this.isPptActive = false // 重置幻灯片按钮状态
			this.isClothesActive = false // 重置换装按钮状态
			this.isFrameActive = false // 重置组局按钮状态
			this.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态

			this.getScheduleTree()
			this.showDrawer2 = true
		},
		openDrawer() {
			this.showDrawer = true
		},
		showCloDrawer() {
			this.isScheduleActive = false // 重置日程按钮状态
			this.isPptActive = false // 重置幻灯片按钮状态
			this.isProductPptActive = false
			this.isClothesActive = true // 激活换装按钮
			this.isFrameActive = false // 重置组局按钮状态
			this.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态

			this.showCDrawer = true
			this.closeProductPptList()
		},
		// 处理订阅按钮点击
		handleSubscribe(val) {
			// 跳转到订阅页面

			// 或者关闭蒙版
			this.showSubscriptionMask = val
		},
		// 处理订阅按钮点击
		handleUpgrade(val) {
			// 跳转到订阅页面

			// 或者关闭蒙版
			this.showSubscriptionMask = val
		},
		// 换装数据
		async getImgTree() {
			try {
				const res = await this.$Request.getApi("/bot/api/agentcgetimgtree", {
					botid: this.zhushou.id,
				})
				if (res.status === 1) {
					this.headimgurlData = res.data
				}
			} catch (e) {
				console.error("获取形象树失败", e)
			}
		},
		// 点击切换形象换装
		async handleClothesClick(item) {
			this.showCDrawer = false
			this.zhushou.app_key = item.app_key
			this.zhushou.headimgurl = item.headimgurl
			this.noFace = item.headimgurl
			// 在这里可以添加处理点击图片的逻辑
			this.isThink = false
			if (pc) {
				this.isFace = true
				// 模拟连接断开
				pc.close()
				pc = null
				// 重置重连计数
				reconnectAttempts = 0
				let formData = {
					id: this.zhushou.id,
					clientid: this.clientid,
				}
				this.$Request.getApi("/bot/api/agentlink", formData).then((res) => {
					if (res.status == 0) {
						// uni.showModal({
						// 	showCancel: false,
						// 	title: "暂无可用链路,请联系管理员！",
						// 	content: res.message,
						// })
						// return
					}
				})

				const response = await fetch(
					"https://human.cycyai.com:10804/idle-node", {
					method: "GET",
					headers: {
						"Content-Type": "application/json",
					},
				}
				)

				const result2 = await response.json()

				if (result2.url != "") {
					this.apibaseurl = result2.url + "/"
					try {
						let response2 = await fetch(
							this.apibaseurl + "imagehuman-unlock-client-id", {
							method: "POST",
							headers: {
								"Content-Type": "application/json",
							},
							body: JSON.stringify({
								client_id: this.clientid,
							}),
						}
						)

						const response = await fetch(
							this.apibaseurl + "imagehuman-lock-client-id", {
							method: "POST",
							headers: {
								"Content-Type": "application/json",
							},
							body: JSON.stringify({
								client_id: this.clientid,
							}),
						}
						)

						const result = await response.json()

						if (result.status === "success") {
							// this.isLocked = true;
							// this.apibaseurl = 'https://human.cycyai.com:8881'+this.baseurl[i];

							let formData2 = {
								id: this.zhushou.id,
								cid: this.clientid,
								baseurl: this.apibaseurl,
							}
							this.$Request
								.getApi("/bot/api/agentlinkping", formData2)
								.then((res) => { })

							let date2 = {
								client_id: this.clientid,
							}
							// let date2 = null;
							this.abortController = new AbortController()
							this.turnoptions = {
								myDate: date2,
								signal: this.abortController.signal,
								url: this.apibaseurl + "imagehuman-get-turn-credentials",
							}
							//h5向app传参，触发事件
							uni.webView.postMessage({
								data: {
									action: "clientid",
									data: this.clientid,
								},
							})
							//h5向app传参，触发事件
							uni.webView.postMessage({
								data: {
									action: "baseurl",
									data: i,
								},
							})
							// break;
						} else {
							// continue;
						}
					} catch (error) { }
				}
			}
		},
		handleRecordStart(e) {
			// 隐藏摄像头（如果已开启）
			if (this.showLocalCamera && this.isIos) {
				this.showLocalCamera = false;
				this.wasCameraActive = true
			}
			this.isRecording = true
			// 兼容 touch 和 mouse
			if (e && e.touches && e.touches.length) {
				this.startY = e.touches[0].clientY
			} else if (e && typeof e.clientY === "number") {
				this.startY = e.clientY
			} else {
				this.startY = 0
			}
			this.startBarAnim()
			this.startVoice()
		},
		handleRecordEnd() {
			this.isRecording = false
			this.stopBarAnim()
			this.endVoice()
		},
		handleRecordMove(e) {
			// 如有需要用 clientY，也要做同样兼容
			let currentY = 0
			if (e && e.touches && e.touches.length) {
				currentY = e.touches[0].clientY
			} else if (e && typeof e.clientY === "number") {
				currentY = e.clientY
			}
		},
		startBarAnim() {
			if (this.useJavaScriptAnimation) {
				// 降级到JavaScript动画
				this.startJavaScriptBarAnim()
			} else {
				// 使用CSS动画，不需要额外操作
			}
		},
		stopBarAnim() {
			if (this.useJavaScriptAnimation) {
				this.stopJavaScriptBarAnim()
			}
		},
		connect() {
			//   var that = this;
			//      var socket = new SockJS('http://47.95.43.65:9999/endpoint-websocket'); //连接上端点(基站)
			//      // stompClient = Stomp.over(socket);           //用stom进行包装，规范协议
			//      // stompClient.connect({}, function (frame) {
			//      //     // console.log('Connected: ' + frame);
			//      //     stompClient.subscribe('/topic/game_chat', function (result) {
			//      //         console.info("result="+result)
			//      //         // showContent(JSON.parse(result.body));
			//      //     });
			//      // });
			//   stompClient = webstomp.over(socket);
			//   stompClient.connect({}, function() {
			//   	stompClient.subscribe("/topic/game_chat", function(message) {
			// 		let result = JSON.parse(message.body);
			//   		console.info("resultMSG:"+result.content);
			// if(result.from == "agent_"+that.zhushou.id+"_stop"){
			// 	// that.ask(e.detail.ask)
			// 	// that.content = result.content;
			// 	// that.send();
			// 	isTransmitting = false;
			// 	dataChannel.send(mystopMessage);
			// 	that.abortFetch();
			// }
			// if(result.from == "agent_"+that.zhushou.id){
			// 	// that.ask(e.detail.ask)
			// 	that.content = result.content;
			// 	that.send();
			// }
			//   	});
			//   });
		},
		handleScroll(e) {
			e.stopPropagation() // 阻止事件冒泡
			e.preventDefault() // 阻止默认行为
		},
		async checkAudioTrackHasSound(mediaStream) {
			this.audioContext = new (window.AudioContext ||
				window.webkitAudioContext)()
			this.analyser = this.audioContext.createAnalyser()
			this.analyser.fftSize = 256

			// 3. 连接音频流
			let source = this.audioContext.createMediaStreamSource(mediaStream)
			source.connect(this.analyser)

			// 4. 开始检测
			let dataArray = new Uint8Array(this.analyser.frequencyBinCount)
			this.analyser.getByteTimeDomainData(dataArray)

			// 调试：打印前 10 个样本值（转换为普通数组）
			const sampleValues = Array.from(dataArray.slice(0, 10))
			// // console.log("音频样本值:", JSON.stringify(sampleValues))

			// 调试：打印统计信息
			// // console.log(
			// 	"最大值:",
			// 	Math.max(...dataArray),
			// 	"最小值:",
			// 	Math.min(...dataArray),
			// 	"中值:",
			// 	dataArray[Math.floor(dataArray.length / 2)]
			// )

			// 计算平均音量（值域 0~128）
			let sum = 0
			for (let i = 0; i < dataArray.length; i++) {
				sum += Math.abs(dataArray[i] - 128) // 计算每个样本的绝对偏移
			}

			let average = sum / dataArray.length

			// 判定逻辑（带防抖）
			// // console.log("sum:", sum)
			// // console.log("dataArray:", dataArray.length)
			// // console.log("average:", average)
			if (average > 3) {
				// 阈值需根据 AI 语音特性调整
				if (!this.isSpeaking) {
					this.isSpeaking = true
					// // console.log("检测到 AI 开始说话")
				}
			} else {
				if (this.isSpeaking) {
					this.isSpeaking = false
					// // console.log("检测到 AI 停止说话")
				}
			}
			let hasSound = false
			return hasSound
		},
		generateClientId() {
			let ClientId =
				uni.getStorageSync("ClientId") ||
				Math.random().toString(36).substr(2, 9)
			uni.setStorageSync("ClientId", ClientId)
			return ClientId
		},
		// 在renderScript中触发的方法
		abortFetch() {
			// 中止请求
			if (this.abortController) {
				this.abortController.abort()
				this.abortController = null
			}
		},
		beReset() {
			let date = {
				session: this.session,
			}
			//  this.$Request.postT("/api/core/user/lporeset",date).then((res) => {
			//  	// console.log(res);
			// // player.play();
			//  });
		},
		// 日程数据
		async getScheduleTree() {
			try {
				// // // console.log('换装接口调用前，botid=====================:', this.zhushou.id);
				const res = await this.$Request.getApi(
					"/bot/api/useragentcgetscheduletree", {
					botid: this.zhushou.id,
					userid: this.userid,
				}
				)
				if (res.status === 1) {
					this.scheduleData = res.data
					// // // console.log('换装数据', this.headimgurlData);
				}
			} catch (e) {
				// console.error('获取形象树失败', e);
			}
		},
		async handleClothesClick2(item) {
			let formData3 = {
				id: item.id,
			}
			this.$Request
				.getApi("/bot/api/agentcdelschedule", formData3)
				.then((res) => {
					if (res.status === 1) {
						this.getScheduleTree()
					}
				})
		},
		showquery(msg) {
			// if(this.issay == false){
			// this.issay = true;
			dataChannel.send(mystopMessage)
			this.sendnumf = 0

			this.content = msg
			this.send()
			// }
			// uni.webView.postMessage({
			// 	  data: {
			// 		  action: '信息',
			// 	  }
			// });
		},
		async getpptData() {
			try {
				// // // console.log('换装接口调用前，botid=====================:', this.zhushou.id);
				const res = await this.$Request.getApi("/bot/api/agentgetpptlist", {
					botid: this.zhushou.id,
				})
				if (res.status === 1) {
					this.pptList = res.data
					// this.headimgurlData = res.data;
					// // // console.log('换装数据', this.headimgurlData);
				}
			} catch (e) {
				console.error("获取形象失败", e)
			}
		},
		async getpptData2() {
			try {
				// // // console.log('换装接口调用前，botid=====================:', this.zhushou.id);
				const res = await this.$Request.getApi("/bot/api/agentgetproductpptlist", {
					botid: this.zhushou.id,
				})
				if (res.status === 1) {
					this.productPptList = res.data
					// this.headimgurlData = res.data;
					// // // console.log('换装数据', this.headimgurlData);
				}
			} catch (e) {
				console.error("获取形象失败", e)
			}
		},
		async closePptList() {
			var that = this
			// uni.showModal({
			// 	title: '提示',
			// 	content: '是否结束PPT讲解？',
			// 	// showCancel: false, // 不显示取消按钮
			// 	success(res) {
			// 		if (res.confirm) {
			that.isScheduleActive = false // 重置日程按钮状态
			that.isPptActive = false // 激活幻灯片按钮
			that.isClothesActive = false // 重置换装按钮状态
			that.isFrameActive = false // 重置组局按钮状态
			that.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态


			that.issayppt = false
			that.isshowppt = false
			that.bannerList = []
			that.current = 0
			isTransmitting = false
			dataChannel.send(mystopMessage)
			var humanvideo = document.getElementById("video2")
			humanvideo.style = that.videostyle
			var humanmsgbot = document.getElementById("msgbot")
			humanmsgbot.style = that.msgbotstyle
			humanmsgbot.style.padding = `0 0 0 2%`
			// 		}
			// 	}
			// });
		},
		async closeProductPptList() {
			var that = this
			// uni.showModal({
			// 	title: '提示',
			// 	content: '是否结束PPT讲解？',
			// 	// showCancel: false, // 不显示取消按钮
			// 	success(res) {
			// 		if (res.confirm) {
			that.issayproductppt = false
			that.isshowproductppt = false
			that.bannerList = []
			that.current = 0
			isTransmitting = false
			dataChannel.send(mystopMessage)
			// 		}
			// 	}
			// });
		},
		async showPptList() {
			this.isScheduleActive = false // 重置日程按钮状态
			this.isPptActive = true // 激活幻灯片按钮
			this.isProductPptActive = false
			this.isClothesActive = false // 重置换装按钮状态
			this.isFrameActive = false // 重置组局按钮状态
			this.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态

			var that = this
			await that.closeProductPptList()
			await that.getpptData()
			// TODO:检查幻灯片列表是否为空
			if (!that.pptList || that.pptList.length === 0) {
				that.isPptActive = false // 重置按钮状态
				uni.showToast({
					title: '暂无幻灯片',
					icon: 'none',
					duration: 1000
				})
				return
			}
			uni.showActionSheet({
				itemList: that.pptList,
				success: function (res) {
					// // console.log('选中了第' + (res.tapIndex) + '个按钮');
					that.issayppt = true
					that.showquery(that.pptList[res.tapIndex])
					var humanvideo = document.getElementById("video2")
					that.videostyle = humanvideo.style
					humanvideo.style.width = `90px`
					humanvideo.style.height = `140px`
					humanvideo.style.transform = `rotate(90deg)`
					humanvideo.style.left = `25%`
					humanvideo.style.top = `83vh`

					var humanmsgbot = document.getElementById("msgbot")
					that.msgbotstyle = humanmsgbot.style
					humanmsgbot.style.width = `136px`
					humanmsgbot.style.height = `44px`
					humanmsgbot.style.transform = `rotate(90deg)`
					humanmsgbot.style.left = `-4.5%`
					humanmsgbot.style.top = `-8vh`
					humanmsgbot.style.opacity = `0.7`
				},
				fail: function (res) {
					that.isPptActive = false
					// that.handleClothesClick(that.headimgurlData[0]);
					// // console.log(res.errMsg);//返回数据
				},
			})
		},

		async showProductPptList() {
			if (this.isshowproductppt) {
				this.isScheduleActive = false // 重置日程按钮状态
				this.isPptActive = false // 激活幻灯片按钮
				this.isProductPptActive = false // 激活讲产品按钮
				this.isClothesActive = false // 重置换装按钮状态
				this.isFrameActive = false // 重置组局按钮状态
				this.isFoodLuckActive = false // 重置食神按钮状态
				this.isVideoActive = false // 重置视频按钮状态

				await this.closeProductPptList()
			} else {
				this.isScheduleActive = false // 重置日程按钮状态
				this.isPptActive = false // 激活幻灯片按钮
				this.isProductPptActive = true // 激活讲产品按钮
				this.isClothesActive = false // 重置换装按钮状态
				this.isFrameActive = false // 重置组局按钮状态
				this.isFoodLuckActive = false // 重置食神按钮状态
				this.isVideoActive = false // 重置视频按钮状态

				var that = this
				await that.getpptData2()
				// 检查讲产品列表是否为空
				if (!that.productPptList || that.productPptList.length === 0) {
					that.isProductPptActive = false // 重置按钮状态
					uni.showToast({
						title: '暂无讲产品',
						icon: 'none',
						duration: 1000
					})
					return
				}
				uni.showActionSheet({
					itemList: that.productPptList,
					success: function (res) {
						// // console.log('选中了第' + (res.tapIndex) + '个按钮');
						that.issayproductppt = true
						that.showquery(that.productPptList[res.tapIndex])
						// var humanvideo = document.getElementById("video2")
						//       that.videostyle = humanvideo.style
						//       humanvideo.style.width = `90px`
						//       humanvideo.style.height = `140px`
						//       humanvideo.style.transform = `rotate(90deg)`
						//       humanvideo.style.left = `25%`
						//       humanvideo.style.top = `83vh`

						//       var humanmsgbot = document.getElementById("msgbot")
						//       that.msgbotstyle = humanmsgbot.style
						//       humanmsgbot.style.width = `136px`
						//       humanmsgbot.style.height = `44px`
						//       humanmsgbot.style.transform = `rotate(90deg)`
						//       humanmsgbot.style.left = `-4.5%`
						//       humanmsgbot.style.top = `-8vh`
						//       humanmsgbot.style.opacity = `0.7`
					},
					fail: function (res) {
						that.isProductPptActive = false;
						// that.handleClothesClick(that.headimgurlData[0]);
						// // console.log(res.errMsg);//返回数据
					},
				})
			}
		},

		async showinfo() {
			this.isThink = false
			if (pc) {
				this.isFace = true
				// // console.log("Testing reconnection...")
				// 模拟连接断开
				pc.close()
				pc = null
				// 重置重连计数
				reconnectAttempts = 0

				let formData = {
					id: this.zhushou.id,
					clientid: this.clientid,
				}
				this.$Request.getApi("/bot/api/agentlink", formData).then((res) => {
					if (res.status == 0) {
						// uni.showModal({
						// 	showCancel: false,
						// 	title: "暂无可用链路,请联系管理员！",
						// 	content: res.message,
						// })
						// return
					}
				})

				const response = await fetch(
					"https://human.cycyai.com:10804/idle-node", {
					method: "GET",
					headers: {
						"Content-Type": "application/json",
					},
				}
				)

				const result2 = await response.json()

				if (result2.url != "") {
					this.apibaseurl = result2.url + "/"
					try {
						let response2 = await fetch(
							this.apibaseurl + "imagehuman-unlock-client-id", {
							method: "POST",
							headers: {
								"Content-Type": "application/json",
							},
							body: JSON.stringify({
								client_id: this.clientid,
							}),
						}
						)

						const response = await fetch(
							this.apibaseurl + "imagehuman-lock-client-id", {
							method: "POST",
							headers: {
								"Content-Type": "application/json",
							},
							body: JSON.stringify({
								client_id: this.clientid,
							}),
						}
						)

						const result = await response.json()

						if (result.status === "success") {
							// this.isLocked = true;
							// this.apibaseurl = 'https://human.cycyai.com:8881'+this.baseurl[i];

							let formData2 = {
								id: this.zhushou.id,
								cid: this.clientid,
								baseurl: this.apibaseurl,
							}
							this.$Request
								.getApi("/bot/api/agentlinkping", formData2)
								.then((res) => { })

							let date2 = {
								client_id: this.clientid,
							}
							// let date2 = null;
							this.abortController = new AbortController()
							this.turnoptions = {
								myDate: date2,
								signal: this.abortController.signal,
								url: this.apibaseurl + "imagehuman-get-turn-credentials",
							}
							//h5向app传参，触发事件
							uni.webView.postMessage({
								data: {
									action: "clientid",
									data: this.clientid,
								},
							})
							//h5向app传参，触发事件
							uni.webView.postMessage({
								data: {
									action: "baseurl",
									data: i,
								},
							})
							// break;
						} else {
							// continue;
						}
					} catch (error) {
						console.error("Error toggling lock:", error)
						// continue;
					}
				}
				// 重新初始化连接
			}
		},
		myfocus(id, mytype) {
			var that = this
			if (mytype == 1) {
				uni.showModal({
					title: "提示",
					content: "是否确定收藏智能体?",
					success: function (res) {
						if (res.confirm) {
							let formData = {
								zsid: id,
								userid: that.userInfo.userid,
								type: mytype,
							}
							that.$Request
								.postApi(
									"/module.php?m=aichat_zhushou_user&a=use&ajax=1",
									formData
								)
								.then((res) => {
									if (res.error == 0) {
										uni.showToast({
											title: "收藏成功",
											icon: "none",
											duration: 1000,
										})
										let swnum = 0
										that.swiperList.forEach((swiper, index) => {
											if (swiper.zsid == id) {
												that.swiperList[swnum].focus = 1
											}
											swnum++
										})
									} else {
										uni.showModal({
											showCancel: false,
											title: "收藏失败",
											content: res.message,
										})
									}
								})
						} else if (res.cancel) {
							// // console.log("用户点击取消")
						}
					},
				})
			} else {
				uni.showModal({
					title: "提示",
					content: "是否确定取消收藏智能体?",
					success: function (res) {
						if (res.confirm) {
							let formData = {
								zsid: id,
								userid: that.userInfo.userid,
								type: mytype,
							}
							that.$Request
								.postApi(
									"/module.php?m=aichat_zhushou_user&a=use&ajax=1",
									formData
								)
								.then((res) => {
									if (res.error == 0) {
										uni.showToast({
											title: "取消收藏成功",
											icon: "none",
											duration: 1000,
										})
										let swnum = 0
										that.swiperList.forEach((swiper, index) => {
											if (swiper.zsid == id) {
												that.swiperList[swnum].focus = 0
											}
											swnum++
										})
									} else {
										uni.showModal({
											showCancel: false,
											title: "取消收藏失败",
											content: res.message,
										})
									}
								})
						} else if (res.cancel) {
							// // console.log("用户点击取消")
						}
					},
				})
			}
		},
		showMsg(newVal) {
			this.isShowMsg = newVal
			this.initScrollBar()
		},
		setShowBtn() {
			this.isShowBtn = !this.isShowBtn
		},
		setV() {
			this.isVolume = !this.isVolume
			if (!this.isVolume) {
				// 假设 videoElement 是你的 <video> 元素，并且它已经通过 srcObject 设置了 WebRTC 视频流
				const stream = audioElement.srcObject

				// 检查 stream 是否有效且包含音频轨道
				if (stream && stream.getAudioTracks().length > 0) {
					const audioTracks = stream.getAudioTracks()
					audioTracks.forEach((track) => {
						track.enabled = false // 禁用音频轨道，实现静音效果
					})
					// // console.log("stream:", stream)
				}
			} else {
				// 假设 videoElement 是你的 <video> 元素，并且它已经通过 srcObject 设置了 WebRTC 视频流
				const stream = audioElement.srcObject

				// 检查 stream 是否有效且包含音频轨道
				if (stream && stream.getAudioTracks().length > 0) {
					const audioTracks = stream.getAudioTracks()
					audioTracks.forEach((track) => {
						track.enabled = true // 启用音频轨道
					})
				}
			}
		},
		changeaudio() {
			// this.audiooff = false;
			// this.startVoice();
			this.bottomSize = 230
			// if (this.isSpeaking) {
			this.isSpeaking = false
			this.showVoice = true

			dataChannel.send(mystopMessage)

			// uni.webView.postMessage({
			// 	  data: {
			// 		  action: 'AI未说话',
			// 	  }
			// });
			// }
		},
		changeaudio2() {
			this.audiooff = true
			this.endVoice()
		},
		getMsgData() {
			let formData = {
				appsecret: this.appSecret,
				userid: this.userid,
			}
			this.$Request.postApi("/bot/api/agentcgetmsg", formData).then((res) => {
				if (res.status == 1) {
					this.list = res.data
					if (this.list.length > 1) {
						this.isMsgnul = false
						this.messageMargins = "53vh 0rpx 0rpx 0rpx"
						// if (this.list[this.list.length - 2].type == 1 || this.list[this.list.length - 2]
						// 	.type == "1") {
						// 	this.askImgMsg = this.list[this.list.length - 2].content;
						// 	// // console.log("askImgMsg:", this.askImgMsg)
						// }
					} else {
						if (this.isHomeWeb) {
							this.messageMargins = this.isIos ?
								"55vh 0rpx 0rpx 0rpx" :
								"53vh 0rpx 0rpx 0rpx"
						} else {
							this.messageMargins = "53vh 0rpx 0rpx 0rpx"
						}
						this.isMsgnul = true
					}
				}
				this.$nextTick(() => {
					this.scrollToBottom()
				})
			})
		},
		// 解析文本内容并生成HTML
		parseTextContentToHtml(content) {
			if (!content) return '';

			// 使用正则表达式替换括号内容，直接使用内联样式
			return content.replace(/[（(][^）)]*[）)]/g, (match) => {
				return `<span style="color: #838383;">${match}</span>`;
			});
		},
		scrollToBottom() {
			this.scrollViewId = "bottom"
			// 确保滚动生效
			setTimeout(() => {
				this.scrollViewId = ""
			}, 200)
		},
		sendMsg(content, sendRole) {
			if (content)
				if (sendRole == "用户") {
					this.iszstalk = false
					this.msgtext = content
					this.msgtext = this.msgtext.substring(0, 18) + "..."
					this.msgimg = this.zhushou.imgurl
				} else {
					this.iszstalk = true
					this.msgtext = content
					this.msgtext = this.msgtext.substring(0, 18) + "..."
					this.msgimg = this.zhushou.imgurl
				}
			if (sendRole != "用户") {
				setTimeout(() => {
					let formData = {
						id: this.zhushou.id,
						message: content,
						role: sendRole,
						userid: this.userid,
					}
					this.$Request
						.getApi("/bot/api/agentcsendmsg", formData)
						.then((res) => {
							if (res.status == 1) {
								this.getMsgData()
								this.initScrollBar()
							} else {
								uni.showModal({
									showCancel: false,
									title: "聊天数据发送失败",
									content: res.message,
								})
							}
						})
					// this.getMsgData();
				}, 1000 * this.sendnumf)
			} else {
				let formData = {
					id: this.zhushou.id,
					message: content,
					role: sendRole,
					userid: this.userid,
				}
				this.$Request.getApi("/bot/api/agentcsendmsg", formData).then((res) => {
					if (res.status == 1) {
						this.getMsgData()
						this.initScrollBar()
					} else {
						uni.showModal({
							showCancel: false,
							title: "聊天数据发送失败",
							content: res.message,
						})
					}
				})
				// this.getMsgData();
			}
		},
		acceptData(data) {
			// some code
			let date2 = null
			if (data.type == "success") {
				// // console.log(data.end);
				this.alive = false
				if (data.end == 1) {
					// // console.log(data.prompt);
					this.sendMsg(data.prompt, this.zhushou.title)
					this.isSend = false
					this.alive = true
				}

				date2 = {
					session: this.session,
					audio: data.audio,
					frame: data.frame,
				}
				setTimeout(() => {
					// this.$Request.postT("/api/core/user/lpoaudioctrl",date2).then((res2) => {
					// 	// console.log(res2);
					// });
				}, 5000)
			}
		},

		onAppBackground() {
			// 应用进入后台，尝试保持连接
			if (pc) {
				// 暂停视频流减少资源占用，但保持连接
				const videoElement = document.getElementById("video_map")?.querySelector("video");
				if (videoElement) {
					videoElement.pause();
				}
			}
		},
		// 新增方法：暂停媒体流
		pauseMediaStreams() {
			if (videoElement && videoElement.srcObject) {
				const stream = videoElement.srcObject;
				stream.getTracks().forEach(track => {
					track.enabled = false;
				});
			}
		},

		// 新增方法：恢复媒体流
		restoreMediaStreams() {
			if (pc && pc.connectionState === "connected" || pc.connectionState === 'completed') {
				// console.log('开始恢复')
				// 获取所有远程流
				const receivers = pc.getReceivers()

				receivers.forEach((receiver) => {
					if (receiver.track && receiver.track.readyState === "live") {
						if (receiver.track.kind === "video") {
							if (videoElement) {
								videoElement
									.play()
									.catch((e) => console.log("Video resume failed:", e))
							}
						} else if (receiver.track.kind === "audio") {
							// console.log(document.querySelector("audio"))
							if (!audioElement) {
								audioElement = document.createElement("audio")
								audioElement.id = "audio"
								audioElement.autoplay = true
								document.body.appendChild(audioElement)
							}
							// 重新设置音频流
							const stream = new MediaStream([receiver.track])
							audioElement.srcObject = stream
							audioElement
								.play()
								.catch((e) => console.log("Audio resume failed:", e))
						}
						// 添加接收器，表示希望接收音频和视频
						pc.addTransceiver("audio", {
							direction: "recvonly",
						})
						pc.addTransceiver("video", {
							direction: "recvonly",
						})
						// ✅ 移除了错误的 addTransceiver 调用
						// addTransceiver 只应在初始连接时调用，不应在恢复时调用
					}
				})
			}
		},
		acceptStatusData(data) {
			// // console.log("StatusData:", data)
			// some code
			// let date2 = null;
			if (data.type == "success") {
				// // console.log(data.end);
				//this.loading = false;
				let date2 = {
					client_id: this.clientid,
				}
				// let date2 = null;
				this.abortController = new AbortController()
				this.turnoptions = {
					myDate: date2,
					signal: this.abortController.signal,
					url: this.apibaseurl + "imagehuman-get-turn-credentials",
				}
			} else if (data.type == "star") { } else {
				// this.baseurl[0].islink = true;
				// let nolink = true;
				// for(let i = 0; i < 8; i++) {
				//  if(!this.baseurl[i].islink.islink){
				//   this.baseurl[index].islink = true;
				//   this.apibaseurl = this.baseurl[index].url;
				//   nolink = false;
				//   let date = {
				//   	client_id: 'cycy_'+this.userInfo.userid.toString(),
				//   };
				//   // // let date2 = null;
				//   this.abortController = new AbortController();
				//   this.statusoptions = {
				//   	myDate: date,
				//   	signal: this.abortController.signal,
				//   	url: this.apibaseurl+'/imagehuman-connection-status'
				//   };
				//   break;
				//  }else{
				//   nolink = true;
				//  }
				// }
				// if(nolink){
				// if(data.data != null){
				// this.noFace = this.zhushou.imgurl;
				// this.isFace = false;
				// uni.showModal({
				// 	showCancel: false,
				// 	title: '连接失败',
				// 	content: '暂无可用链路,无法连接动态智能体,即将以静态方式进行展示。',
				// });
				// }
				// }
			}
		},

		acceptTurnData(data) {
			// // console.log("TurnData:", data.data)
			var that = this
			// some code
			// let date2 = null;
			if (data.type == "success") {
				let voiceEncoding = "pcm"
				let date2 = {
					query: this.showTimbre,
					user_uuid: this.zhushou.id,
					// role: this.role,
					role_name: this.role_name,
					role_desc: this.role_desc,
					voice_id: this.voiceId,
					voice_encoding: voiceEncoding,
				}

				this.TurnDataUsername = data.data.username
				this.TurnDataPassword = data.data.password
				const pcConfig = {
					iceServers: [{
						urls: [
							"turn:220.197.166.216:3471",
							"turn:220.197.166.216:3472",
							"turn:220.197.166.216:3473"
						],
						username: data.data.username,
						credential: data.data.password,
						credentialType: "password"
					}],
					iceTransportPolicy: "all",
					bundlePolicy: "max-bundle",
					rtcpMuxPolicy: "require",
					iceCandidatePoolSize: 10, // 增加候选池大小
					// 关键配置：优化重连
					iceConnectionTimeout: 30000, // 30秒超时
					iceCheckingTimeout: 5000 // 5秒检查超时
				};
				pc = new RTCPeerConnection(pcConfig)

				// Create DataChannel with specific configuration
				dataChannel = pc.createDataChannel("interaction", {
					ordered: true,
					maxRetransmits: 3,
				})

				this.mydataChannel = dataChannel
				dataChannel.onopen = function () {
					// // console.log("Data channel is open")
					isTransmitting = false
					// isDataChannelOpen = true;
					// flushMessageQueue();

					// Send button event listener
					// document.querySelector('sendButton').addEventListener('click', async function() {
					// // console.log('sendButton');
					function log(message) {
						// // console.log(message)
					}

					// Utility: Split string into chunks
					function splitStringIntoChunks(str, chunkSize) {
						const chunks = []
						for (let i = 0; i < str.length; i += chunkSize) {
							chunks.push(str.slice(i, i + chunkSize))
						}
						return chunks
					}

					// Send large message handler
					function sendLargeMessage(dataChannel, message, chunkSize = 16000) {
						const chunks = splitStringIntoChunks(message, chunkSize)
						const totalChunks = chunks.length

						chunks.forEach((chunk, index) => {
							const messageToSend = JSON.stringify({
								type: "chunk",
								index: index,
								total: totalChunks,
								data: chunk,
							})
							if (isTransmitting) {
								dataChannel.send(messageToSend)
							}
						})

						const endMessage = JSON.stringify({
							type: "end",
						})
						if (isTransmitting) {
							dataChannel.send(endMessage)
						}
					}

					// 工具函数：睡眠指定时间（毫秒）
					function sleep(ms) {
						return new Promise((resolve) => setTimeout(resolve, ms))
					}

					async function testRoleCustomTextAudioStream(
						query,
						userUuid,
						roleName,
						roleDesc,
						voiceId,
						voiceEncoding
					) {
						const HTTP = "https://human.cycyai.com:10801"
						const url = `${HTTP}/api/role/stream-audio`

						isTransmitting = true

						const requestBody = {
							text: query,
							voice_id: voiceId,
							voice_encoding: voiceEncoding,
						}

						let buffer = ""

						try {
							const response = await fetch(url, {
								method: "POST",
								headers: {
									"Content-Type": "application/json",
								},
								body: JSON.stringify(requestBody),
							})

							if (response.ok) {
								log(`[${userUuid}] Request started, status: ${response.status}`)

								const reader = response.body.getReader()
								const decoder = new TextDecoder("utf-8")

								that.isFace = false
								that.issaykcb = false
								that.connect()
								// 初始化滚动条
								that.initScrollBar()

								while (true) {
									const {
										done,
										value
									} = await reader.read()
									if (done) break

									const chunk = decoder.decode(value, {
										stream: true,
									})
									buffer += chunk

									let jsonIndex
									while ((jsonIndex = buffer.indexOf("<Json>")) !== -1) {
										log("Detected <Json> separator")

										const jsonObject = buffer.substring(0, jsonIndex).trim()
										buffer = buffer.substring(jsonIndex + "<Json>".length)

										try {
											// jsonObject = jsonObject.replace(/\\/g, "");
											const data = JSON.parse(jsonObject)

											const textChunk = data.text || ""
											const audioChunk = data.audio || ""

											// // console.log(`textChunk:`,textChunk);
											// // console.log(`audioChunk:`,audioChunk);
											// if (!that.isSpeaking) {
											// 	that.isSpeaking = true;
											// 	that.showVoice = false;
											// 	// console.log('检测到 AI 开始说话');
											// 	uni.webView.postMessage({
											// 		  data: {
											// 			  action: 'AI说话',
											// 		  }
											// 	});
											// }

											const messageToSend = JSON.stringify({
												text: textChunk,
												audio: audioChunk,
											})

											// // console.log(`mydataChannel:`, dataChannel)

											if (dataChannel.readyState === "open") {
												log(`DataChannel is open`)
												sendLargeMessage(dataChannel, messageToSend)
												log(`Data sent via DataChannel`)
											} else {
												log("DataChannel not open, message queued")
												messageQueue.push(messageToSend)
											}

											await sleep(3000)
										} catch (err) {
											const data = JSON.parse(jsonObject)
											log(`JSON parsing error: ${data}, Error: ${err.message}`)
										}
									}
								}
							} else {
								const errorText = await response.text()
								log(`Error: ${response.status}, ${errorText}`)
							}
						} catch (error) {
							log(`Request failed: ${error.message}`)
						}
					}

					// var messageInput = document.querySelector('messageInput');
					// // console.log("开场白", that.showTimbre)
					// that.isFace = false;
					// // console.log("Video isFace:", that.isFace);
					// that.isFace = true;
					// // console.log("Video isFace:", that.isFace);
					var message = "."
					if (that.issaykcb) {
						message = that.showTimbre
					}
					if (message) {
						const query = message
						const userUuid = "Agent_" + that.userid
						const roleName = that.role_name
						const roleDesc = that.role_desc
						const voiceId = that.voiceId
						const voiceEncoding = "pcm" // 或 "wav"

						testRoleCustomTextAudioStream(
							query,
							userUuid,
							roleName,
							roleDesc,
							voiceId,
							voiceEncoding
						)
						// messageInput.value = ""; // 清空输入框
					}

					// 如果需要直接发送输入框的内容，可以启用以下代码
					// var messageInput = document.getElementById('messageInput');
					// var message = messageInput.value;
					// if (message) {
					//   dataChannel.send(message);
					//   // console.log("Sent message to server:", message);
					//   messageInput.value = ""; // 清空输入框
					// }
					// });
				}
				pc.ontrack = function (event) {
					// // console.log("Received track:", event.track.kind)
					// // console.log("Stream received:", event.streams[0])

					// 可以在这里给 track 本身再添加监听器
					event.track.onmute = function () {
						// // console.log("Track was muted:", event.track.kind)
					}

					event.track.onunmute = function () {
						// // console.log("Track was unmuted:", event.track.kind)
					}

					if (event.track.kind === "video") {
						// // console.log("Video track received")
						// videoElement = document.getElementById("AiVideo")
						videoElement = document
							.getElementById("video_map")
							.querySelector("video")
						videoElement.srcObject = event.streams[0]
						// // console.log("Video stream connected to element")
					} else if (event.track.kind === "audio") {
						// // console.log("Audio track received")
						audioElement = document.querySelector("audio")
						if (!audioElement) {
							audioElement = document.createElement("audio")
							audioElement.id = "audio"
							audioElement.autoplay = true
							document.body.appendChild(audioElement)
							// // console.log("Audio element created")
						}
						audioElement.srcObject = event.streams[0]
						// // console.log("Audio stream connected to element")
					}
				}

				// 添加接收器，表示希望接收音频和视频
				pc.addTransceiver("audio", {
					direction: "recvonly",
				})
				pc.addTransceiver("video", {
					direction: "recvonly",
				})

				// 修改 offer 发送部分
				pc.createOffer({
					iceRestart: true
				})
					.then(function (offer) {
						return pc.setLocalDescription(offer)
					})
					.then(function () {
						return fetch(that.apibaseurl + "imagehuman-webrtc-offer", {
							method: "POST",
							body: JSON.stringify({
								sdp: pc.localDescription.sdp,
								type: pc.localDescription.type,
								client_id: that.clientid,
								image_id: that.zhushou.app_key,
							}),
							headers: {
								"Content-Type": "application/json",
							},
						})
					})
					.then(function (response) {
						if (!response.ok) {
							throw new Error(`Server error: ${response.status}`)
						}
						return response.json()
					})
					.then(function (answer) {
						return pc.setRemoteDescription(new RTCSessionDescription(answer))
					})
					.catch(function (e) {
						console.error("Connection error:", e)
						// that.handleClothesClick(that.zhushou)
						this.handleConnectionFailure();
					})

				pc.oniceconnectionstatechange = () => {
					switch (pc.iceConnectionState) {
						case "connected":
							// console.log('WebRTC连接成功');
							that.reconnectAttempts = 0;
							that.isIceRestarting = false; // 重置重启标记
							clearTimeout(that.iceDisconnectedTimeout);
							break;

						case "disconnected":
							// 如果正在选择媒体，不要触发重连
							if (that.isChoosingMedia) {
								// console.log('正在选择媒体，忽略断开事件');
								break;
							}
							// console.log('WebRTC连接断开');
							// 缩短等待时间，快速响应
							that.iceDisconnectedTimeout = setTimeout(() => {
								// 再次检查状态
								if (pc.iceConnectionState === "disconnected" && !that.isIceRestarting && !
									that.isChoosingMedia) {
									// console.log('🔄 尝试ICE重启恢复连接');
									that.tryIceRestartWithRetry(3).then(success => {
										if (success) {
											// console.log('✅ 连接已恢复');
										} else {
											// console.log('❌ 连接恢复失败，请手动重新进入');
											uni.showModal({
												title: '连接中断',
												content: '连接恢复失败，请重新进入页面',
												showCancel: false
											});
										}
									});
								}
							}, 3000); // 增加到3秒，给更多恢复时间
							break;

						case "failed":
							// ✅ 如果正在选择媒体，忽略
							if (that.isChoosingMedia) {
								// console.log('⚠️ 正在选择媒体，忽略失败事件');
								break;
							}

							// console.log('❌ WebRTC连接失败');

							// ✅ 尝试最后一次恢复
							if (!that.isIceRestarting) {
								// console.log('🔄 连接失败，尝试最后一次恢复');
								that.tryIceRestartWithRetry(2).then(success => {
									if (!success) {
										// console.log('❌ 最终恢复失败');
										uni.showModal({
											title: '连接失败',
											content: '无法恢复连接，请重新进入页面',
											showCancel: false
										});
									}
								});
							}
							break;
						case "closed":
							// console.log('WebRTC连接关闭');
							that.cleanupWebRTC();
							break;
					}
				};

				// 添加连接状态监控
				pc.onconnectionstatechange = () => {
					// console.log("PeerConnection State:", pc.connectionState);
				};
			} else if (data.type == "star") { } else {
				if (data.data != null) {
					this.noFace = this.zhushou.headimgurl
					this.isFace = false
					uni.showModal({
						showCancel: false,
						title: "连接失败",
						content: "凭证获取失败,无法连接动态智能体,即将以静态方式进行展示。",
					})
				}
			}
		},
		openLocation() {
			uni.openLocation({
				longitude: 113.3298396012573,
				latitude: 22.961803525530176,
				name: "祈福新村",
				address: "祈福新村",
			})
		},
		// 跳转
		tn(e) {
			uni.navigateTo({
				url: e,
			})
		},
		// 初始化滚动
		initScrollBar() {
			// this.bottomSize = 180;
			setTimeout(() => {
				this.scrollViewId = ""
				setTimeout(() => {
					this.scrollViewId = "bottom"
					this.scrollToBottom()
					setTimeout(() => {
						this.scrollViewId = ""
					}, 100)
				}, 100)
			}, 100)
		},
		// 监听输入聚焦
		inputFocus(e) {
			this.setScrollHeight(e.detail.height)
			this.initScrollBar()
		},
		inputBlur() { },
		// 设置scroll的高度
		setScrollHeight(descHeight = 0) {
			// #ifdef MP-WEIXIN
			this.scrollHeight = `calc(100vh - 110rpx - ${descHeight}px)`
			// #endif
			// #ifdef APP-PLUS
			this.scrollHeight = `calc(100vh - 110upx - ${descHeight}px)`
			// #endif
			// #ifdef H5
			this.scrollHeight = `calc(50vh - 110upx - 88rpx - ${descHeight}px)`
			// #endif
		},
		// 切换选择
		togglePicker(height = 0, type = "") {
			this.showEmoji = false
			this.showFile = false
			let status = height > 0 ? true : false

			switch (type) {
				case "emoji":
					this.showEmoji = status
					break
				case "file":
					this.showFile = status
					break
			}

			if (this.showFile) {
				this.bottomSize = 340
			} else {
				this.bottomSize = 180
			}

			setTimeout(() => {
				this.setScrollHeight(height)
				this.initScrollBar()
			}, 50)
		},
		// 切换语音与编辑
		toggleEdit(bool) {
			if (!bool) {
				this.bottomSize = 230
				this.isVideo = true
				// uni.webView.postMessage({
				// 	data: {
				// 		action: "视频通话",
				// 	},
				// })
			}
			this.isEdit = bool
			this.isFocus = bool
			this.setScrollHeight(0)
		},
		// 开始录音
		startVoice() {
			// // console.log("开始录音")
			this.showVoice = true
			this.isask = true

			// if(this.sendnumf != 0){
			isTransmitting = false
			dataChannel.send(mystopMessage)
			this.sendnumf = 0
			// }
			//h5向app传参，触发事件
			uni.webView.postMessage({
				data: {
					action: "ksly",
				},
			})
		},
		// 结束录音
		endVoice() {
			this.showVoice = false
			this.isask = false
			//h5向app传参，触发事件
			uni.webView.postMessage({
				data: {
					action: "jsly",
				},
			})
			setTimeout(() => {
				this.restoreMediaStreams()
				if (this.isVideoActive && this.isIos) {
					this.showLocalCamera = true;
					this.wasCameraActive = false;
					this.$nextTick(() => {
						setTimeout(() => {
							this.switchCamera(this.currentFacingMode)
						}, 100)
					})
				}
			}, 200)
		},
		// 换装数据
		async getMeetingShow() {
			try {
				// // // console.log('换装接口调用前，botid=====================:', this.zhushou.id);
				const res = await this.$Request.getApi("/bot/api/agentmeetingshow", {
					botid: this.zhushou.id,
				})
				if (res.status === 1) {
					this.handlgiteClothesClick(res.data)
					// this.headimgurlData = res.data;
					// // // console.log('换装数据', this.headimgurlData);
				}
			} catch (e) {
				console.error("获取形象失败", e)
			}
		},
		async startMeeting() {
			this.isScheduleActive = false // 重置日程按钮状态
			this.isPptActive = false // 重置幻灯片按钮状态
			this.isProductPptActive = false
			this.isClothesActive = false // 重置换装按钮状态
			this.isFrameActive = false // 重置组局按钮状态
			this.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态

			var that = this
			await that.closeProductPptList()
			// await that.getMeetingShow()
			uni.showActionSheet({
				itemList: ["开始会议"],
				success: function (res) {
					// // console.log(og('选中了第' + (res.tapIndex + 1) + '个按钮');
					if (res.tapIndex == 0) {
						that.getMeetingShow()
						that.isMeeting = true
						if (this.sendnumf != 0) {
							that.getMeetingShow()
							that.isMeeting = true
							isTransmitting = false
							dataChannel.send(mystopMessage)
							this.sendnumf = 0

							//h5向app传参，触发事件
							uni.webView.postMessage({
								data: {
									action: "开始会议记录",
									data: res.tapIndex,
								},
							})
						}
					}
				},
				fail: function (res) {
					// that.handleClothesClick(that.headimgurlData[0])
					// // console.log(og(res.errMsg);//返回数据
				},
			})
			// uni.showModal({
			// 	title: '提示',
			// 	content: '是否需要开启会议记录？',
			// 	// showCancel: false, // 不显示取消按钮
			// 	success(res) {
			// 		if (res.confirm) {
			// 	that.isMeeting = true;
			// 			// if(this.sendnumf != 0){
			// 			  isTransmitting = false;
			// 			  dataChannel.send(mystopMessage);
			// 						this.sendnumf = 0;
			// 			// }

			// 			//h5向app传参，触发事件
			// 			uni.webView.postMessage({
			// 		  data: {
			// 			  action: '开始会议记录',
			// 		  }
			// 			});
			// 		}
			// 	}
			// });
		},
		endMeeting() {
			this.isScheduleActive = false // 重置日程按钮状态
			this.isPptActive = false // 重置幻灯片按钮状态
			this.isClothesActive = false // 重置换装按钮状态
			this.isFrameActive = false // 重置组局按钮状态
			this.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态

			this.handleClothesClick(this.headimgurlData[0])
			var that = this
		},
		// 处理换装按钮状态更新
		onClothesActiveUpdate(value) {
			this.isClothesActive = value
		},
		// 处理日程按钮状态更新
		onScheduleActiveUpdate(value) {
			this.isScheduleActive = value
		},
		endMeeting() {
			this.isScheduleActive = false // 重置日程按钮状态
			this.isPptActive = false // 重置幻灯片按钮状态
			this.isClothesActive = false // 重置换装按钮状态
			this.isFrameActive = false // 重置组局按钮状态
			this.isFoodLuckActive = false // 重置食神按钮状态
			this.isVideoActive = false // 重置视频按钮状态

			this.handleClothesClick(this.headimgurlData[0])
			var that = this
			uni.showModal({
				title: "提示",
				content: "是否需要结束会议记录？",
				// showCancel: false, // 不显示取消按钮
				success(res) {
					if (res.confirm) {
						that.isMeeting = false
						uni.webView.postMessage({
							data: {
								action: "结束会议记录",
							},
						})
					}
				},
			})
		},
		// 上传
		upload(filePath) {
			// this.$util.loading('上传中')
			uni.uploadFile({
				url: "https://tk.cycyai.com:6501/api/core/user/upload",
				name: "file",
				filePath,
				formData: {
					userId: "168168168",
				},
				success: (res) => {
					uni.hideLoading()
					let data = JSON.parse(res.data)
					// this.pushMessage(data.data, 'voice')
				},
				fail: (err) => {
					uni.hideLoading()
				},
			})
		},
		// 播放录音
		playVoice(item) {
			// if(this.voicePlayingId){
			// 	this.voicePlayingId = ''
			// }else{
			// 	this.voicePlayingId = item.id
			// 	innerAudioContext.src = item.content
			// 	innerAudioContext.play()
			// }
		},
		// 长按
		longPress(msg) {
			// this.record.start().then(() => {
			//   recording = true;
			// });
			// this.record.stopToText("16k_zh").then((text) => {
			//     // console.log(text);
			//   }).finally(() => {
			//     recording = false;
			//   });
			// let data = {
			// 	type: 'single',
			// 	source: this.fromUserId,
			// 	dest: this.toUserId,
			// 	timestamp: new Date().getTime(),
			// 	msg: {
			// 		id: msg.id,
			// 		fromUserId: msg.fromUserId,
			// 		toUserId: msg.toUserId,
			// 		type: 'cancel',
			// 		content: msg.content
			// 	}
			// }
			// uni.sendSocketMessage({
			// 	data: JSON.stringify(data),
			// 	success: res=>{
			// 		// 撤销本地消息
			// 		this.list = this.list.map(item=>{
			// 			item.type = item.id == msg.id ? 'cancel' : item.type
			// 			return item
			// 		})
			// 	}
			// })
		},
		// 获取位置
		getLocation() {
			uni.getLocation({
				success: (res) => {
					let {
						latitude,
						longitude
					} = res
					uni.chooseLocation({
						latitude,
						longitude,
						success: (chooseRes) => {
							this.pushMessage(JSON.stringify(chooseRes), "map")
						},
					})
				},
			})
		},
		// 打开位置
		openLocation(content) {
			let {
				latitude,
				longitude
			} = JSON.parse(content)
			uni.openLocation({
				latitude,
				longitude,
			})
		},
		// 发送图片
		uploadImage(sourceType = ["album"]) {
			uni.chooseImage({
				sourceType,
				success: (chooseImageRes) => {
					const tempFilePaths = chooseImageRes.tempFilePaths

					tempFilePaths.forEach((temp) => {
						this.$util.loading("上传中")
						uni.uploadFile({
							url: this.$api.upload,
							filePath: temp,
							formData: {
								userId: this.fromUserId,
							},
							name: "file",
							header: this.$util.getHeader(),
							success: (uploadRes) => {
								uni.hideLoading()
								let data = JSON.parse(uploadRes.data)
								this.pushMessage(data.data, "image")
							},
							fail: (err) => {
								uni.hideLoading()
							},
						})
					})
				},
			})
		},
		// 视频通话
		video() {
			// // console.log(this.session);
			// let date = {
			//     session: this.session
			// };
			// this.$Request.postT("/api/core/user/lpostop",date).then((res) => {
			// 	// console.log(res);
			// 	player.stop();
			// 	this.session = null;
			// });
			uni.webView.postMessage({
				data: {
					action: "视频通话",
				},
			})
			this.isVideo = true
			// this.showVoice = true;
			// this.nextCas.changeCamera({ x: 0, y: 1.65, z: 0.58 },{ x: 0, y: 1.61, z: -0.45 },100);
		},
		close() {
			// this.nextCas.changeCamera({ x: 0, y: 1.65, z: 1.6 },{ x: 0, y: 1.61, z: 1.2 },500);
			uni.webView.postMessage({
				data: {
					action: "结束通话",
				},
			})
			if (this.showVoice == true) {
				this.endVoice()
			}
			// this.showVoice = false;
			this.isVideo = false
		},
		// 发送图片消息监听
		sendImageMessage() {
			this.getMsgData()
			setTimeout(() => {
				this.restoreMediaStreams()
			}, 500)
		},
		// 发送消息
		async send() {
			// ✅ 添加状态检查
			if (this.isPerformingIceRestart) {
				console.warn('⚠️ 正在执行 ICE restart，暂时无法发送消息');
				uni.showToast({
					title: '连接正在恢复，请稍后再试',
					icon: 'none',
					duration: 1500
				});
				return;
			}

			// ✅ 检查 DataChannel 状态
			if (!dataChannel || dataChannel.readyState !== 'open') {
				console.warn('⚠️ DataChannel 未就绪');
				uni.showToast({
					title: '连接未就绪，请稍后再试',
					icon: 'none',
					duration: 1500
				});
				return;
			}
			// 初始化滚动条
			this.initScrollBar()
			// cb ? cb() : this.togglePicker(0, 'file')
			// this.nextCas.changeCamera({ x: 0, y: 1.65, z: 1.6 },{ x: 0, y: 1.61, z: 1.2 },500);
			this.abortFetch()
			this.beReset()
			this.isThink = true
			this.messageMargins = "53vh 0rpx 0rpx 0rpx"
			this.isSend = true
			// if (this.askImgMsg != null) {
			// 	this.askImgMsg = null;
			// }
			this.getMsgData();
			await this.sendMsg(this.content, "用户")
			uni.setStorageSync("token", this.tokenInfo)
			let voiceEncoding = "pcm"
			this.voiceId = this.zhushou.timbre_code

			if (this.current > 0) {
				this.isstopppt = true;
				this.isstopproductppt = true;
				// this.isshowppt = false;
				this.current = this.current - 1
			}

			var that = this
			// let date = {
			//     query: this.content,
			//     user_uuid: this.userid,
			//     // role: this.role,
			// 	role_name: this.role_name,
			// 	role_desc: this.role_desc,
			// 	voice_id: this.voiceId,
			// 	voice_encoding: voiceEncoding,
			// };

			that.sendnumf = 0

			if (dataChannel && dataChannel.readyState === "open") {
				if (that.sendnumf != 0) {
					isTransmitting = false
					dataChannel.send(mystopMessage)
				}
				// // console.log("Stop message sent")
			} else {
				// // console.log("DataChannel not available or not open")
			}

			// var message = this.content;
			// // console.log('sendButton');
			function log(message) {
				// // console.log(message)
			}

			// Utility: Split string into chunks
			function splitStringIntoChunks(str, chunkSize) {
				const chunks = []
				for (let i = 0; i < str.length; i += chunkSize) {
					chunks.push(str.slice(i, i + chunkSize))
				}
				return chunks
			}

			// Send large message handler
			function sendLargeMessage(dataChannel, message, chunkSize = 16000) {
				const chunks = splitStringIntoChunks(message, chunkSize)
				const totalChunks = chunks.length

				chunks.forEach((chunk, index) => {
					const messageToSend = JSON.stringify({
						type: "chunk",
						index: index,
						total: totalChunks,
						data: chunk,
					})
					if (isTransmitting) {
						dataChannel.send(messageToSend)
					}
				})

				const endMessage = JSON.stringify({
					type: "end",
				})
				if (isTransmitting) {
					dataChannel.send(endMessage)
				}
			}

			// 工具函数：睡眠指定时间（毫秒）
			function sleep(ms) {
				return new Promise((resolve) => setTimeout(resolve, ms))
			}

			async function testRoleCustomTextAudioStream(
				query,
				userUuid,
				roleName,
				roleDesc,
				voiceId,
				voiceEncoding
			) {
				const HTTP = "https://human.cycyai.com:10801"
				const url = `${HTTP}/api/role/custom-stream-text-audio`

				isTransmitting = true

				const requestBody = {
					query: query,
					user_uuid: userUuid,
					role_name: roleName,
					role_desc: roleDesc,
					voice_id: voiceId,
					voice_encoding: voiceEncoding,
				}

				let buffer = ""

				dataChannel.send(mystopMessage)

				that.abortController = new AbortController()

				try {
					const response = await fetch(url, {
						signal: that.abortController.signal,
						method: "POST",
						headers: {
							"Content-Type": "application/json",
						},
						body: JSON.stringify(requestBody),
					})

					if (response.ok) {
						log(`[${userUuid}] Request started, status: ${response.status}`)

						const reader = response.body.getReader()
						const decoder = new TextDecoder("utf-8")

						while (true) {
							const {
								done,
								value
							} = await reader.read()
							if (done) break

							const chunk = decoder.decode(value, {
								stream: true,
							})
							buffer += chunk

							let jsonIndex
							while ((jsonIndex = buffer.indexOf("<Json>")) !== -1) {
								log("Detected <Json> separator")

								const jsonObject = buffer.substring(0, jsonIndex).trim()
								buffer = buffer.substring(jsonIndex + "<Json>".length)

								try {
									const data = JSON.parse(jsonObject)
									const textChunk = data.text || ""
									const audioChunk = data.audio || ""

									// if (!that.isSpeaking) {
									// 	that.isSpeaking = true;
									// 	that.showVoice = false;
									// 	// console.log('检测到 AI 开始说话');
									// 	uni.webView.postMessage({
									// 		  data: {
									// 			  action: 'AI说话',
									// 		  }
									// 	});
									// }

									// // console.log(`textChunk:`,textChunk);
									// // console.log(`audioChunk:`,audioChunk);
									if (textChunk != "<End>") {
										that.isThink = false
										that.sendMsg(textChunk, that.zhushou.title)
										that.sendnumf++
									} else {
										that.isThink = false
										that.sendnumf = 0
										that.issay = false
										that.askImgMsg = null;
									}
									// assistant = assistant + audioChunk;

									const messageToSend = JSON.stringify({
										text: textChunk,
										audio: audioChunk,
									})

									if (dataChannel.readyState === "open") {
										log(`DataChannel is open`)
										sendLargeMessage(dataChannel, messageToSend)
										log(`Data sent via DataChannel`)
									} else {
										log("DataChannel not open, message queued")
										messageQueue.push(messageToSend)
									}

									await sleep(3000)
								} catch (err) {
									log(
										`JSON parsing error: ${jsonObject}, Error: ${err.message}`
									)
								}
							}
						}
					} else {
						const errorText = await response.text()
						log(`Error: ${response.status}, ${errorText}`)
					}
				} catch (error) {
					log(`Request failed: ${error.message}`)
				}
			}

			async function testRoleCustomAudioStream(
				query,
				userUuid,
				roleName,
				roleDesc,
				voiceId,
				voiceEncoding
			) {
				const HTTP = "https://human.cycyai.com:10801"
				const url = `${HTTP}/api/role/stream-audio`

				isTransmitting = true

				const requestBody = {
					text: query,
					voice_id: voiceId,
					voice_encoding: voiceEncoding,
				}

				let buffer = ""

				dataChannel.send(mystopMessage)

				that.abortController = new AbortController()

				try {
					const response = await fetch(url, {
						signal: that.abortController.signal,
						method: "POST",
						headers: {
							"Content-Type": "application/json",
						},
						body: JSON.stringify(requestBody),
					})

					if (response.ok) {
						log(`[${userUuid}] Request started, status: ${response.status}`)

						const reader = response.body.getReader()
						const decoder = new TextDecoder("utf-8")

						while (true) {
							const {
								done,
								value
							} = await reader.read()
							if (done) break

							const chunk = decoder.decode(value, {
								stream: true,
							})
							buffer += chunk

							let jsonIndex
							while ((jsonIndex = buffer.indexOf("<Json>")) !== -1) {
								log("Detected <Json> separator")

								const jsonObject = buffer.substring(0, jsonIndex).trim()
								buffer = buffer.substring(jsonIndex + "<Json>".length)

								try {
									const data = JSON.parse(jsonObject)
									const textChunk = data.text || ""
									const audioChunk = data.audio || ""

									if (textChunk != "<End>") {
										that.isThink = false
										that.sendMsg(textChunk, that.zhushou.title)
										that.sendnumf++
									} else {
										that.isThink = false
										that.sendnumf = 0
									}

									const messageToSend = JSON.stringify({
										text: textChunk,
										audio: audioChunk,
									})

									if (dataChannel.readyState === "open") {
										log(`DataChannel is open`)
										sendLargeMessage(dataChannel, messageToSend)
									} else {
										log("DataChannel not open.")
									}
								} catch (err) {
									log(
										`JSON parsing error: ${jsonObject}, Error: ${err.message}`
									)
								}
							}
						}
					} else {
						const errorText = await response.text()
						log(`Error: ${response.status}, ${errorText}`)
					}
				} catch (error) {
					log(`Request failed: ${error.message}`)
				}
			}

			var message = this.content

			if (message) {
				const query = message
				const userUuid = "Agent_" + this.zhushou.id
				const roleName = this.role_name
				const roleDesc = this.role_desc
				const voiceId = this.voiceId
				const voiceEncoding = "pcm" // 或 "wav"

				let formData2 = {
					id: this.zhushou.id,
					userid: this.userid,
					query: message,
					querytype: this.querytype,
				}
				this.$Request.getApi("/bot/api/querygagent", formData2).then((res) => {
					if (res.status == 1) {
						// this.role_desc = res.message;
						testRoleCustomAudioStream(
							res.message,
							userUuid,
							roleName,
							roleDesc,
							voiceId,
							voiceEncoding
						)
					} else if (res.status == 2) {
						this.bannerList = res.message
						this.isshowppt = true
						this.sendppt(this.bannerList[0].title)
						// // console.log(res.message);
					} else if (res.status == 3) {
						this.querytype = 0;
						testRoleCustomAudioStream(
							res.message,
							userUuid,
							roleName,
							roleDesc,
							voiceId,
							voiceEncoding
						)
						//h5向app传参，触发事件
						uni.webView.postMessage({
							data: {
								action: "日程提醒",
								data: res.data,
							},
						})
					} else if (res.status == 4) {
						this.querytype = 0;
						testRoleCustomAudioStream(
							res.message,
							userUuid,
							roleName,
							roleDesc,
							voiceId,
							voiceEncoding
						)
					} else if (res.status == 5) {
						this.bannerList = res.message
						this.isshowproductppt = true
						this.sendppt(this.bannerList[0].title)
						// // console.log(res.message);
					} else if (res.status == 6) {
						var that = this;
						that.friendList = res.data.fname;
						var friendidList = res.data.fid;
						var mymessage = res.message;
						uni.showActionSheet({
							itemList: that.friendList,
							success: function (res) {
								// that.issayproductppt = true
								// that.showquery(that.productPptList[res.tapIndex])
								let formData3 = {
									userid: that.userid,
									friendid: friendidList[res.tapIndex],
									time: mymessage[0],
									doevent: mymessage[1],
								}
								that.$Request.getApi("/bot/api/agentcsetimreminder", formData3)
									.then((res) => {
										if (res.status == 1) {
											that.querytype = 0;
											testRoleCustomAudioStream(
												res.message,
												userUuid,
												roleName,
												roleDesc,
												voiceId,
												voiceEncoding
											)
										} else {
											testRoleCustomAudioStream(
												res.message,
												userUuid,
												roleName,
												roleDesc,
												voiceId,
												voiceEncoding
											)
										}
										return;
									})
							},
							fail: function (res) {
								// that.isProductPptActive = false;
								return;
							},
						})
						// // console.log(res.message);
					} else if (res.status == 7) {
						var that = this;
						that.friendList = res.data.fname;
						var friendidList = res.data.fid;
						var mymessage = res.message;
						uni.showActionSheet({
							itemList: that.friendList,
							success: function (res) {
								// that.issayproductppt = true
								// that.showquery(that.productPptList[res.tapIndex])
								let formData3 = {
									userid: that.userid,
									groupid: friendidList[res.tapIndex],
									time: mymessage[0],
									doevent: mymessage[1],
								}
								that.$Request.getApi("/bot/api/agentcsetimgroupreminder",
									formData3).then((res) => {
										if (res.status == 1) {
											that.querytype = 0;
											testRoleCustomAudioStream(
												res.message,
												userUuid,
												roleName,
												roleDesc,
												voiceId,
												voiceEncoding
											)
										} else {
											testRoleCustomAudioStream(
												res.message,
												userUuid,
												roleName,
												roleDesc,
												voiceId,
												voiceEncoding
											)
										}
										return;
									})
							},
							fail: function (res) {
								// that.isProductPptActive = false;
								return;
							},
						})
					} else if (res.status == 8) {
						this.querytype = 0;
						testRoleCustomAudioStream(
							res.message,
							userUuid,
							roleName,
							roleDesc,
							voiceId,
							voiceEncoding
						)
						var that = this;

						uni.showActionSheet({
							itemList: ["日程提醒", "预约好友", "工作组提醒"],
							success: function (res) {
								// // console.log(og('选中了第' + (res.tapIndex + 1) + '个按钮');
								// if(this.sendnumf != 0){
								isTransmitting = false
								dataChannel.send(mystopMessage)
								// }
								if (res.tapIndex == 0) {
									isTransmitting = false
									dataChannel.send(mystopMessage)
									that.querytype = 1;
									testRoleCustomAudioStream(
										"好的,您可以按照 'XXX点,提醒我XXX' 的格式跟我描述日程提醒内容。",
										userUuid,
										roleName,
										roleDesc,
										voiceId,
										voiceEncoding
									)
								} else if (res.tapIndex == 1) {
									isTransmitting = false
									dataChannel.send(mystopMessage)
									that.querytype = 2;
									testRoleCustomAudioStream(
										"好的,您可以按照 'XXX点,帮我约XXX去XXX' 的格式跟我描述预约好友内容。",
										userUuid,
										roleName,
										roleDesc,
										voiceId,
										voiceEncoding
									)
								} else {
									isTransmitting = false
									dataChannel.send(mystopMessage)
									that.querytype = 3;
									testRoleCustomAudioStream(
										"好的,您可以按照 'XXX点,工作组XXX提醒XXX' 的格式跟我描述工作组提醒内容。",
										userUuid,
										roleName,
										roleDesc,
										voiceId,
										voiceEncoding
									)
								}

							},
							fail: function (res) {
								isTransmitting = false
								dataChannel.send(mystopMessage)
								that.querytype = 0;
								// // console.log(og(res.errMsg);//返回数据
							},
						})
						// // console.log(res.message);
					} else if (res.status == 9) {
						var that = this;
						if (!cameraVideoElement) {
							testRoleCustomAudioStream(
								"老板，您需要打开摄像头我才能看得见哦！",
								userUuid,
								roleName,
								roleDesc,
								voiceId,
								voiceEncoding
							)
						} else {
							let base64file = that.capturePhoto()
							let params = {
								appsecret: this.appSecret,
								role: "用户",
								userid: this.userid,
								file: base64file,
							}
							this.$Request
								.postApi("/bot/api/agentcsendimgmsg", params)
								.then((res) => {
									if (res.status === 1) {
										that.getMsgData();
										that.askImgMsg = res.data;
										let queryarr = {
											text: query,
											image_url: that.askImgMsg,
										}
										testRoleCustomTextAudioStream(
											queryarr,
											userUuid,
											roleName,
											roleDesc,
											voiceId,
											voiceEncoding
										)
									} else {
										uni.showToast({
											title: res.message || "发送消息失败",
											icon: "none",
										});
									}
								})
								.catch(() => {
									uni.showToast({
										title: "网络错误",
										icon: "none",
									});
								});
						}
					} else {
						var that = this;
						if (that.askImgMsg == null) {
							testRoleCustomTextAudioStream(
								query,
								userUuid,
								roleName,
								roleDesc,
								voiceId,
								voiceEncoding
							)
						} else {
							let queryarr = {
								text: query,
								image_url: that.askImgMsg,
							}
							testRoleCustomTextAudioStream(
								queryarr,
								userUuid,
								roleName,
								roleDesc,
								voiceId,
								voiceEncoding
							)
						}
					}
				})

				// testRoleCustomTextAudioStream(query, userUuid, roleName, roleDesc, voiceId, voiceEncoding);
				this.content = ""
				// messageInput.value = ""; // 清空输入框
			}

			// 如果需要直接发送输入框的内容，可以启用以下代码
			// var messageInput = document.getElementById('messageInput');
			// var message = messageInput.value;
			// if (message) {
			//   dataChannel.send(message);
			//   // console.log("Sent message to server:", message);
			//   messageInput.value = ""; // 清空输入框
			// }

			// this.testRoleCustomTextAudioStream(this.content, this.userid, this.role_name, this.role_desc, this.voiceId, voiceEncoding);
			// let date2 = null;
			// this.abortController = new AbortController();
			// this.options = {
			//     myDate: date,
			// 	signal: this.abortController.signal,
			// 	url: 'https://ai.cycyai.com:8000/api/role/custom-stream-text-audio'
			// };

			//       const url = 'http://47.92.138.153:8000/api/role/custom-stream-text-audio';
			//       let eventData = '';
			// let XFsession = this.session;
			//       // 发送 POST 请求
			//       const body = {
			//     query: this.content,
			//     user_uuid: "0001",
			//     // role: this.role,
			// 	role_name: this.role_name,
			// 	role_desc: this.role_desc,
			// 	voice_id: this.voiceId,
			// 	voice_encoding: "pcm"
			// };

			//    fetch(url, {
			//      method: 'POST', // 请求方法
			//      headers: {
			//        'Content-Type': 'application/json' // 设置请求的 Content-Type
			//      },
			//      body: JSON.stringify(body) // 将请求体转换为 JSON 字符串
			//    })
			//    .then(response => {
			//         if (response.body) {
			//              // 将body属性转换为ReadableStream
			//              const reader = response.body.getReader();
			//              // 处理流数据
			//              reader.read().then(function processData({ done, value }) {
			//                if (done) {
			//                  // console.log('No more data to process');
			//                  return;
			//                }
			// const chunk = new TextDecoder().decode(value, { stream: !done })
			// // // console.log(chunk);
			// const lines = chunk.split('<Json>') // 逐条解析后端返回数据
			// if(lines.length == 1){
			// 	eventData = eventData + lines[0];
			// }else{
			// 	eventData = eventData + '"}';
			// 	let obj2 = JSON.parse(eventData);
			// 	date2 = {
			// 		session: XFsession,
			// 		audio: obj2.audio
			// 	};
			// 	// console.log("next:",obj2.text);

			// 	globalVar = obj2.text;
			// 	eventData = '';
			// }
			//                // 这里可以处理流数据，例如将其作为二进制数据保存到文件中
			//                // 假设我们要将数据保存到一个变量中
			//                let chunks = [];
			//                chunks.push(value);

			//                // 继续读取流数据
			//                return reader.read().then(processData);
			//              });
			//        }
			//    })
			//    .then(data => {
			//      // console.log(data);
			//    })
			//    .catch(error => {
			//      console.error('请求出错:', error);
			//    });

			// this.$Request.postJson("/api/role/stream-text-audio", date).then((res) => {
			// this.$Request.postJson("/api/role/custom-stream-text-audio", date).then((res) => {
			// 	// let date2 = {
			// 	//     text: res
			// 	// };
			// 	// this.$Request.postT("/api/core/user/tts", date2).then((res2) => {
			// 	// this.$Request.postJsonH("/api/v1/tts", date2).then((res2) => {
			// 		// // console.log(res2);
			// 		// res2.data.ttsInfo.replace(/\\/g, '\');
			// 		// var obj = JSON.parse(res.data.audio);
			// 		// // console.log(obj);
			// 		// const arrayBuffer = uni.base64ToArrayBuffer(obj.data);
			// 		// const innerAudioContext = wx.createInnerAudioContext();
			// 		// innerAudioContext.src = obj.data;
			// 		// const arrayBuffer = uni.base64ToArrayBuffer('data:audio/mp3;base64,'+ obj.data);
			// 		// innerAudioContext.play();
			// 		// const arrayBuffer = innerAudioContext.src;
			// 		// // console.log(arrayBuffer);
			// 		// console.log('分段数据:', res);
			// 		let obj = res.split('<Json>');
			// 		for (let i = 0; i < obj.length-1; i++) {
			// 			date2 = null;
			// 			let obj2 = JSON.parse(obj[i]);
			// 			if (i == obj.length-2) {
			// 				// console.log("last:",obj2.text);
			// 			}else{
			// 				// setTimeout(() => {
			// 				  date2 = {
			// 				      session: this.session,
			// 				  	  audio: obj2.audio
			// 				  };
			// 				  // console.log("next:",obj2.text);
			// 				  this.$Request.postT("/api/core/user/lpoaudioctrl",date2).then((res2) => {
			// 				  	// console.log(res2);
			// 				  });
			// 				// }, 15000);
			// 			}
			// 		}
			// 		// // console.log(obj);
			// 		//   this.nextCas.speakByAudio(res.data.audio, {
			// 		//     onEnd: () => {
			// 		//       // console.log("结束");
			// 		//     },
			// 		//     onStart: () => {
			// 		//       // console.log("开始");
			// 		//     },
			// 		//   });
			// 	// });
			//     // // console.log(res);
			// 	// this.nextCas.speak(res, {
			// 	//   onEnd: () => {
			// 	//     // console.log("onEnd");
			// 	//   },
			// 	//   onStart: () => {
			// 	//     // console.log("onStart");
			// 	//   },
			// 	// });
			// });
			// this.nextCas.ask(this.content);
			this.content = ""
			// this.isSend = false;
			this.pushMessage(this.content, "text", () => {
				this.content = ""
			})
		},
		sendppt(pptcontent) {
			if (this.isMeeting) {
				return
			}
			// 初始化滚动条
			this.initScrollBar()
			// cb ? cb() : this.togglePicker(0, 'file')
			// this.nextCas.changeCamera({ x: 0, y: 1.65, z: 1.6 },{ x: 0, y: 1.61, z: 1.2 },500);
			this.abortFetch()
			this.beReset()
			this.isThink = true
			this.isSend = true
			// this.sendMsg(this.content, '用户');
			uni.setStorageSync("token", this.tokenInfo)
			let voiceEncoding = "pcm"
			this.voiceId = this.zhushou.timbre_code

			var that = this
			// let date = {
			//     query: this.content,
			//     user_uuid: this.userid,
			//     // role: this.role,
			// 	role_name: this.role_name,
			// 	role_desc: this.role_desc,
			// 	voice_id: this.voiceId,
			// 	voice_encoding: voiceEncoding,
			// };

			that.sendnumf = 0

			if (dataChannel && dataChannel.readyState === "open") {
				if (that.sendnumf != 0) {
					isTransmitting = false
					dataChannel.send(mystopMessage)
				}
				// // console.log(og('Stop message sent');
			} else {
				// // console.log(og('DataChannel not available or not open');
			}

			// var message = this.content;
			// // console.log(og('sendButton');
			function log(message) {
				// // console.log(og(message);
			}

			// Utility: Split string into chunks
			function splitStringIntoChunks(str, chunkSize) {
				const chunks = []
				for (let i = 0; i < str.length; i += chunkSize) {
					chunks.push(str.slice(i, i + chunkSize))
				}
				return chunks
			}

			// Send large message handler
			function sendLargeMessage(dataChannel, message, chunkSize = 16000) {
				const chunks = splitStringIntoChunks(message, chunkSize)
				const totalChunks = chunks.length

				chunks.forEach((chunk, index) => {
					const messageToSend = JSON.stringify({
						type: "chunk",
						index: index,
						total: totalChunks,
						data: chunk,
					})
					if (isTransmitting) {
						dataChannel.send(messageToSend)
					}
				})

				const endMessage = JSON.stringify({
					type: "end",
				})
				if (isTransmitting) {
					dataChannel.send(endMessage)
				}
			}

			// 工具函数：睡眠指定时间（毫秒）
			function sleep(ms) {
				return new Promise((resolve) => setTimeout(resolve, ms))
			}

			async function testRoleCustomTextAudioStream(
				query,
				userUuid,
				roleName,
				roleDesc,
				voiceId,
				voiceEncoding
			) {
				const HTTP = "https://human.cycyai.com:10801"
				const url = `${HTTP}/api/role/custom-stream-text-audio`

				isTransmitting = true

				const requestBody = {
					query: query,
					user_uuid: userUuid,
					role_name: roleName,
					role_desc: roleDesc,
					voice_id: voiceId,
					voice_encoding: voiceEncoding,
				}

				let buffer = ""

				dataChannel.send(mystopMessage)

				that.abortController = new AbortController()

				try {
					const response = await fetch(url, {
						signal: that.abortController.signal,
						method: "POST",
						headers: {
							"Content-Type": "application/json",
						},
						body: JSON.stringify(requestBody),
					})

					if (response.ok) {
						log(`[${userUuid}] Request started, status: ${response.status}`)

						const reader = response.body.getReader()
						const decoder = new TextDecoder("utf-8")

						while (true) {
							const {
								done,
								value
							} = await reader.read()
							if (done) break

							const chunk = decoder.decode(value, {
								stream: true,
							})
							buffer += chunk

							let jsonIndex
							while ((jsonIndex = buffer.indexOf("<Json>")) !== -1) {
								log("Detected <Json> separator")

								const jsonObject = buffer.substring(0, jsonIndex).trim()
								buffer = buffer.substring(jsonIndex + "<Json>".length)

								try {
									const data = JSON.parse(jsonObject)
									const textChunk = data.text || ""
									const audioChunk = data.audio || ""

									// if (!that.isSpeaking) {
									// 	that.isSpeaking = true;
									// 	that.showVoice = false;
									/// // console.log(og('检测到 AI 开始说话');
									// 	uni.webView.postMessage({
									// 		  data: {
									// 			  action: 'AI说话',
									// 		  }
									// 	});
									// }

									// // console.log(og(`textChunk:`,textChunk);
									// // console.log(og(`audioChunk:`,audioChunk);
									if (textChunk != "<End>") {
										that.isThink = false
										that.sendMsg(textChunk, that.zhushou.title)
										that.sendnumf++
									} else {
										that.isThink = false
										that.sendnumf = 0
										that.issay = false
									}
									// assistant = assistant + audioChunk;

									const messageToSend = JSON.stringify({
										text: textChunk,
										audio: audioChunk,
									})

									if (dataChannel.readyState === "open") {
										log(`DataChannel is open`)
										sendLargeMessage(dataChannel, messageToSend)
										log(`Data sent via DataChannel`)
									} else {
										log("DataChannel not open, message queued")
										messageQueue.push(messageToSend)
									}

									await sleep(3000)
								} catch (err) {
									log(
										`JSON parsing error: ${jsonObject}, Error: ${err.message}`
									)
								}
							}
						}
					} else {
						const errorText = await response.text()
						log(`Error: ${response.status}, ${errorText}`)
					}
				} catch (error) {
					log(`Request failed: ${error.message}`)
				}
			}

			async function testRoleCustomAudioStream(
				query,
				userUuid,
				roleName,
				roleDesc,
				voiceId,
				voiceEncoding
			) {
				const HTTP = "https://human.cycyai.com:10801"
				const url = `${HTTP}/api/role/stream-audio`

				isTransmitting = true

				const requestBody = {
					text: query,
					voice_id: voiceId,
					voice_encoding: voiceEncoding,
				}

				let buffer = ""

				dataChannel.send(mystopMessage)

				that.abortController = new AbortController()

				try {
					const response = await fetch(url, {
						signal: that.abortController.signal,
						method: "POST",
						headers: {
							"Content-Type": "application/json",
						},
						body: JSON.stringify(requestBody),
					})

					if (response.ok) {
						log(`[${userUuid}] Request started, status: ${response.status}`)

						const reader = response.body.getReader()
						const decoder = new TextDecoder("utf-8")

						while (true) {
							const {
								done,
								value
							} = await reader.read()
							if (done) break

							const chunk = decoder.decode(value, {
								stream: true,
							})
							buffer += chunk

							let jsonIndex
							while ((jsonIndex = buffer.indexOf("<Json>")) !== -1) {
								log("Detected <Json> separator")

								const jsonObject = buffer.substring(0, jsonIndex).trim()
								buffer = buffer.substring(jsonIndex + "<Json>".length)

								try {
									const data = JSON.parse(jsonObject)
									const textChunk = data.text || ""
									const audioChunk = data.audio || ""

									if (textChunk != "<End>") {
										that.isThink = false
										that.sendMsg(textChunk, that.zhushou.title)
										that.sendnumf++
									} else {
										that.isThink = false
										that.sendnumf = 0
									}

									const messageToSend = JSON.stringify({
										text: textChunk,
										audio: audioChunk,
									})

									if (dataChannel.readyState === "open") {
										log(`DataChannel is open`)
										sendLargeMessage(dataChannel, messageToSend)
									} else {
										log("DataChannel not open.")
									}
								} catch (err) {
									log(
										`JSON parsing error: ${jsonObject}, Error: ${err.message}`
									)
								}
							}
						}
					} else {
						const errorText = await response.text()
						log(`Error: ${response.status}, ${errorText}`)
					}
				} catch (error) {
					log(`Request failed: ${error.message}`)
				}
			}

			var message = pptcontent

			if (message) {
				const query = message
				const userUuid = "Agent_" + this.zhushou.id
				const roleName = this.role_name
				const roleDesc = this.role_desc
				const voiceId = this.voiceId
				const voiceEncoding = "pcm" // 或 "wav"

				testRoleCustomAudioStream(
					query,
					userUuid,
					roleName,
					roleDesc,
					voiceId,
					voiceEncoding
				)

				// testRoleCustomTextAudioStream(query, userUuid, roleName, roleDesc, voiceId, voiceEncoding);
				this.content = ""
				// messageInput.value = ""; // 清空输入框
			}

			this.content = ""
			// this.isSend = false;
			this.pushMessage(this.content, "text", () => {
				this.content = ""
			})
		},
		ask(content) {
			// this.nextCas.changeCamera({ x: 0, y: 1.65, z: 1.6 },{ x: 0, y: 1.61, z: 1.2 },500);
			this.isSend = true
			this.sendMsg(content, "用户")
			uni.setStorageSync("token", this.tokenInfo)
			let voiceEncoding = "pcm"
			this.voiceId = this.zhushou.timbre_code
			let date = {
				query: this.content,
				user_uuid: this.userid,
				// role: this.role,
				role_name: this.role_name,
				role_desc: this.role_desc,
				voice_id: this.voiceId,
				voice_encoding: voiceEncoding,
			}
			// let date2 = null;

			this.options = {
				myDate: date,
			}
			// this.$Request.postJson("/api/role/stream-text-audio", date).then((res) => {
			// this.$Request.postJson("/api/role/custom-stream-text-audio", date).then((res) => {
			// 			const stream = this.nextCas.createSpeakAudioStream();

			// 			stream.onEnd = () => {
			// 			  // console.log("演讲开始");
			// 			};
			// 			stream.onEnd = () => {
			// 			  // console.log("演讲结束");
			// 			};

			// 			let obj = res.split('<Json>');
			// 			let obj2 = null;
			// 			for (let i = 0; i < obj.length-1; i++) {
			// 				obj2 = JSON.parse(obj[i]);
			// 				if (i == obj.length-2) {
			// 					// console.log("last:",obj2.text);
			// 				    stream.last();
			// 				}else{
			// 					// console.log("next:",obj2.text);
			// 					stream.next(obj2.audio);
			// 				}
			// 			}
			// 		});
			// this.nextCas.ask(this.content);
			this.content = ""
			this.pushMessage(this.content, "text", () => {
				this.content = ""
			})
		},
		// 推送消息
		pushMessage(content, type = "text", cb = () => { }) {
			// 组合消息体：需要保存在本地数据库的数据
			let msgData = {
				fromUserId: this.fromUserId,
				userFace: uni.getStorageSync("userFace"),
				toUserId: this.toUserId,
				type,
				content,
			}

			// 本地保存
			// uni.request({
			// 	method: 'POST',
			// 	url: this.$api.addSingleMsg,
			// 	data: msgData,
			// 	header: this.$util.getHeader(),
			// 	success: res=>{
			// 		if(res.data.code){
			// 			return this.$util.toast(res.data.code)
			// 		}
			// 		let msgId = res.data.data

			// 		// 判断是否为非文本
			// 		if(!['text', 'map'].includes(type)){
			// 			msgData.content = this.$api.staticPath + msgData.content
			// 		}

			// 		// 发送单聊消息
			// 		this.$xbcim.sendSingle({
			// 			content: msgData.content,
			// 			msgType: type,
			// 			source: this.fromUserId,
			// 			target: this.toUserId,
			// 			extra: {
			// 				id: msgId,
			// 				userFace: uni.getStorageSync('userFace')
			// 			}
			// 		})

			// 		// 加入信息
			// 		this.list.push({
			// 			source: this.fromUserId,
			// 			target: this.toUserId,
			// 			content: msgData.content,
			// 			userFace: uni.getStorageSync('userFace'),
			// 			type: 'single',
			// 			msgType: type
			// 		})

			// 		// 初始化滚动条
			// 		this.initScrollBar()
			// 		cb ? cb() : this.togglePicker(0, 'file')
			// 	}
			// })
		},
		// 获取记录
		getList() {
			// uni.request({
			// 	url: this.$api.getSingleRecord,
			// 	data: {
			// 		fromUserId: this.fromUserId,
			// 		toUserId: this.toUserId
			// 	},
			// 	header: this.$util.getHeader(),
			// 	success: res=>{
			// 		this.list = res.data.data.map(item=>{
			// 			if(['voice', 'image'].includes(item.type)){
			// 				item.content = this.$api.staticPath+item.content
			// 			}
			// 			if(item.toUserFace){
			// 				item.toUserFace = this.$api.staticPath+item.toUserFace
			// 			}
			// 			// 为了和socket的字段一致，此处做一个转换；
			// 			// 数据表字段可以直接设置为source、target和msgType
			// 			item.source = item.fromUserId
			// 			item.target = item.toUserId
			// 			item.msgType = item.type
			// 			return item
			// 		})
			// 		this.scrollViewId = ''
			// 		setTimeout(()=>{
			// 			this.scrollViewId = 'bottom'
			// 			setTimeout(()=>{this.scrollViewId = ''}, 100)
			// 		}, 100)
			// 	}
			// })
		},
		handleTopRightIconClick() {
			// 在这里添加右上角图标的点击处理逻辑
		},
		handleMenuItemClick(item) {
			// 在这里添加菜单项点击处理逻辑
			this.activeMenuItem = item
		},
		checkCSSAnimationSupport() {
			// 检测是否支持CSS动画
			const supportsCSSAnimation = CSS.supports("animation", "name 1s")

			if (!supportsCSSAnimation) {
				console.warn("CSS动画不支持，降级到JavaScript动画")
				this.useJavaScriptAnimation = true
			} else {
				this.useJavaScriptAnimation = false
			}
		},
		startJavaScriptBarAnim() {
			if (this.barAnimTimer) return
			let lastUpdate = 0
			const animate = () => {
				const now = Date.now()
				if (now - lastUpdate > 200) {
					// 降低频率到200ms
					this.barHeights = this.barHeights.map((h, i) => {
						const base = 16,
							range = 16,
							t = now / 250 + i * 0.1
						return base + Math.abs(Math.sin(t)) * range
					})
					lastUpdate = now
				}
				this.barAnimTimer = requestAnimationFrame(animate)
			}
			this.barAnimTimer = requestAnimationFrame(animate)
		},

		stopJavaScriptBarAnim() {
			if (this.barAnimTimer) {
				cancelAnimationFrame(this.barAnimTimer)
				this.barAnimTimer = null
			}
			this.barHeights = Array(13).fill(24)
		},
	},
}
</script>
<script module="renderScript" lang="renderjs">
	export default {
		methods: {
			onChange(newValue, oldValue, ownerInstance) {
				const url = 'https://ai.cycyai.com:8000/api/role/custom-stream-text-audio';
				let eventData = '';
				let myframe = 0;
				let prompt = '';
				let end = 0;
				fetch(newValue.url, {
						signal: newValue.signal,
						method: 'POST', // 请求方法
						headers: {
							'Content-Type': 'application/json' // 设置请求的 Content-Type
						},
						body: JSON.stringify(newValue.myDate) // 将请求体转换为 JSON 字符串
					})
					.then(response => {
						if (response.body) {
							// 将body属性转换为ReadableStream
							const reader = response.body.getReader();
							// 处理流数据
							reader.read().then(function processData({
								done,
								value
							}) {
								if (done) {
									// // console.log('No more data to process');
									return;
								}
								const chunk = new TextDecoder().decode(value, {
									stream: !done
								})
								// // console.log(chunk);
								const lines = chunk.split('<Json>') // 逐条解析后端返回数据
								// // console.log(lines);
								if (lines.length == 1) {
									eventData = eventData + lines[0];
								} else if (lines.length == 2) {
									eventData = eventData + lines[0];
									// eventData = eventData + '"}';
									// // console.log(eventData);
									let obj2 = JSON.parse(eventData);
									// // console.log("next:", obj2.text);
									if (obj2.text == "<End>") {
										prompt = prompt;
										end = 1;
									} else {
										prompt = prompt + obj2.text;
									}
									if (myframe > 1) {
										myframe = 1;
									}
									ownerInstance.callMethod('acceptData', {
										type: 'success',
										audio: obj2.audio,
										frame: myframe,
										prompt: prompt,
										end: end
									})
									myframe = myframe + 1;
									eventData = '';
								} else {
									eventData = eventData + lines[0];
									// eventData = eventData + '"}';
									// // console.log(eventData);
									let obj2 = JSON.parse(eventData);
									// // console.log("next:", obj2.text);
									if (obj2.text == "<End>") {
										prompt = prompt;
									} else {
										prompt = prompt + obj2.text;
									}
									if (myframe > 1) {
										myframe = 2;
									}
									end = 1;
									ownerInstance.callMethod('acceptData', {
										type: 'success',
										audio: obj2.audio,
										frame: myframe,
										prompt: prompt,
										end: end
									})
									myframe = myframe + 1;
									eventData = '';
								}
								// 这里可以处理流数据，例如将其作为二进制数据保存到文件中
								// 假设我们要将数据保存到一个变量中

								// 继续读取流数据
								return reader.read().then(processData);
							});
						}
					})
					.catch(error => {
						ownerInstance.callMethod('acceptData', {
							type: 'error'
						})
					});

			},
			checkConnectionStatus(newValue, oldValue, ownerInstance) {
				const url = 'https://human.cycyai.com:8881/work1091/imagehuman-connection-status';
				let eventData = '';
				let myframe = 0;
				let prompt = '';
				let end = 0;
				if (newValue.url != '') {
					fetch(newValue.url, {
							signal: newValue.signal,
							method: 'POST',
							headers: {
								'Content-Type': 'application/json'
							},
							body: JSON.stringify(newValue.myDate) // 将请求体转换为 JSON 字符串
						})
						.then(response => response.json())
						.then(data => {
							if (!data.connected) {
								ownerInstance.callMethod('acceptStatusData', {
									type: 'success',
									data: data
								});
							} else {
								ownerInstance.callMethod('acceptStatusData', {
									type: 'error',
									data: data
								});
							}
						})
						.catch(error => {
							console.error('Error checking connection status:', error);
							ownerInstance.callMethod('acceptStatusData', {
								type: 'error',
								data: error
							});
						});

				} else {
					ownerInstance.callMethod('acceptStatusData', {
						type: 'star'
					});
				}
			},
			getTurnCredentials(newValue, oldValue, ownerInstance) {
				const url = 'https://human.cycyai.com:10803/imagehuman-get-turn-credentials';
				let eventData = '';
				let myframe = 0;
				let prompt = '';
				let end = 0;
				if (newValue.url != '') {
					fetch(newValue.url, {
							signal: newValue.signal,
							method: 'POST',
							headers: {
								'Content-Type': 'application/json'
							},
							body: JSON.stringify(newValue.myDate) // 将请求体转换为 JSON 字符串
						})
						.then(response => response.json())
						.then(data => {
							if (data.status === 403) {
								ownerInstance.callMethod('acceptTurnData', {
									type: 'error',
									data: null
								});
							} else {
								ownerInstance.callMethod('acceptTurnData', {
									type: 'success',
									data: data
								});
							}
						})
						.catch(error => {
							// console.error('Error fetching TURN credentials:', error);
							ownerInstance.callMethod('acceptTurnData', {
								type: 'error',
								data: null
							});
						});

				} else {
					ownerInstance.callMethod('acceptTurnData', {
						type: 'star'
					});
				}
			},
		}
	}
</script>
<style lang="scss" scoped>
.template-reserve {
	width: 100%;
	height: 100vh;
	min-height: 100%;
	position: relative;
	top: 0;
	left: 0;
}

/* 胶囊*/
.tn-custom-nav-bar__back {
	width: 100%;
	height: 100%;
	position: relative;
	display: flex;
	justify-content: space-evenly;
	align-items: center;
	box-sizing: border-box;
	background-color: rgba(0, 0, 0, 0.15);
	border-radius: 20rpx;
	border: 1rpx solid rgba(255, 255, 255, 0.5);
	color: #ffffff;
	font-size: 18px;

	.icon {
		display: block;
		flex: 1;
		margin: auto;
		text-align: center;
	}
}

page {
	margin: 0;
	padding: 0;
	background: #262626;
}

.section {
	background: white;
	border-radius: 12px;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
	margin-bottom: 20px;
	width: 100%;
}

.video-section {
	width: 100%;
}

video {
	width: 100%;
	background: #000;
	display: block;
}

.qsflex-container {
	display: flex;
	flex-wrap: wrap;
	/* 关键：允许换行 */
	gap: 10rpx;
	/* 元素间距 */
}

.qsflex-item {
	flex: 1;
	/* 均匀分配空间 */
	min-width: 30%;
	/* 关键：控制每行3个 (100%/3 - 间隙) */
	// max-width: 32%; /* 防止内容溢出 */
	box-sizing: border-box;
	/* 确保边距不影响宽度 */
	// margin: 5rpx;
}

.ctxt2 {
	font-family: PingFangSC, PingFang SC;
	font-weight: 400;
	font-size: 12px;
	color: #000;
	line-height: 22px;
	text-align: left;
	font-style: normal;
	opacity: 1;
	/* 确保文字不透明 */
}

.ring2 {
	position: absolute;
	top: 45%;
	left: 50%;
	width: 20px;
	transform: translate(-50%, -50%);
}

.ring {
	position: absolute;
	top: 45%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 80px;
	height: 80px;
	background: transparent;
	border: 3px solid #3c3c3c;
	border-radius: 50%;
	text-align: center;
	line-height: 70px;
	font-family: sans-serif;
	font-size: 17px;
	color: #f9f9f9;
	letter-spacing: 4px;
	text-transform: uppercase;
	text-shadow: 0 0 10px #f9f9f9;
	box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);

	text {
		display: block;
		position: absolute;
		top: calc(50% - 2px);
		left: 50%;
		width: 50%;
		height: 4px;
		background: transparent;
		transform-origin: left;
		animation: animate 2s linear infinite;
	}

	text:before {
		content: "";
		position: absolute;
		width: 16px;
		height: 16px;
		border-radius: 50%;
		background: #f9f9f9;
		top: -6px;
		right: -8px;
		box-shadow: 0 0 20px #f9f9f9;
	}
}

.ring:before {
	content: "";
	position: absolute;
	top: -3px;
	left: -3px;
	width: 100%;
	height: 100%;
	border: 3px solid transparent;
	border-top: 3px solid #f9f9f9;
	border-right: 3px solid #f9f9f9;
	border-radius: 50%;
	animation: animateC 2s linear infinite;
}

@keyframes animateC {
	0% {
		transform: rotate(0deg);
	}

	100% {
		transform: rotate(360deg);
	}
}

@keyframes animate {
	0% {
		transform: rotate(45deg);
	}

	100% {
		transform: rotate(405deg);
	}
}

// 本地摄像头容器
.local-camera-container {
	position: fixed;
	bottom: 200rpx;
	left: 20rpx;
	width: 280rpx;
	height: 400rpx;
	z-index: 1000;
	border-radius: 20rpx;
	overflow: hidden;

	.local-camera-video {
		width: 100%;
		height: 100%;
		object-fit: fill; // 确保视频填满容器
		transform: scaleX(-1);
	}

	.camera-controls {
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		align-items: flex-end;
		height: 100%;
		padding: 30rpx 0;
		position: absolute;
		top: 0;
		right: 40rpx;
		z-index: 990;

		.control-icon {
			width: 30rpx;
			height: 30rpx;
			margin-bottom: 4rpx;
		}
	}
}

// 启动摄像头按钮
.start-camera-btn {
	position: fixed;
	top: 100rpx;
	right: 20rpx;
	width: 120rpx;
	height: 120rpx;
	background: rgba(0, 0, 0, 0.6);
	border-radius: 60rpx;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	z-index: 1000;

	.camera-icon {
		width: 40rpx;
		height: 40rpx;
		margin-bottom: 8rpx;
	}

	.camera-text {
		color: #fff;
		font-size: 20rpx;
	}
}


/* 自定义导航栏内容 start */
.custom-nav {
	height: 100%;

	&__back {
		margin: auto 5rpx;
		font-size: 40rpx;
		margin-right: 10rpx;
		margin-left: 30rpx;
		flex-basis: 5%;
	}

	&__search {
		flex-basis: 60%;
		width: 100%;
		height: 100%;

		&__box {
			width: 100%;
			height: 70%;
			padding: 10rpx 0;
			margin: 0 30rpx;
			border-radius: 60rpx 60rpx 0 60rpx;
			font-size: 24rpx;
		}

		&__icon {
			padding-top: 10rpx;
			padding-right: 30rpx;
			margin-left: 20rpx;
			font-size: 50rpx;
		}

		&__text {
			color: #aaaaaa;
		}
	}
}

.logo-image {
	width: 60rpx;
	height: 60rpx;
	position: relative;
	margin-top: -15rpx;
}

.logo-pic {
	background-size: cover;
	background-repeat: no-repeat;
	// background-attachment:fixed;
	background-position: top;
	border-radius: 50%;
}

/* 自定义导航栏内容 end */
/* 博主头像 start*/
.image-circle {
	// padding: 95rpx;
	width: 190rpx;
	height: 190rpx;
	font-size: 40rpx;
	font-weight: 300;
	position: relative;
}

.image-pic {
	background-size: cover;
	background-repeat: no-repeat;
	// background-attachment:fixed;
	background-position: top;
	border-radius: 10rpx;
}

/* 文章内容 start*/
.blogger {
	&__item {
		padding: 30rpx;
	}

	&__author {
		&__btn {
			margin-right: -12rpx;
			opacity: 0.5;
		}
	}

	&__desc {
		line-height: 55rpx;

		&__label {
			padding: 0 20rpx;
			margin: 0rpx 18rpx 0 0;

			&--prefix {
				color: #00ffc8;
				padding-right: 10rpx;
			}
		}

		&__content {}
	}

	&__content {
		margin-top: 18rpx;
		padding-right: 18rpx;

		&__data {
			line-height: 46rpx;
			text-align: justify;
			overflow: hidden;
			transition: all 0.25s ease-in-out;
		}

		&__status {
			margin-top: 10rpx;
			font-size: 26rpx;
			color: #82b2ff;
		}
	}

	&__main-image {
		border-radius: 16rpx;

		&--1 {
			max-width: 80%;
			max-height: 300rpx;
		}

		&--2 {
			max-width: 260rpx;
			max-height: 260rpx;
		}

		&--3 {
			height: 212rpx;
			width: 100%;
		}
	}

	&__count-icon {
		font-size: 40rpx;
		padding-right: 5rpx;
	}

	&__ad {
		width: 100%;
		height: 500rpx;
		transform: translate3d(0px, 0px, 0px) !important;

		::v-deep .uni-swiper-slide-frame {
			transform: translate3d(0px, 0px, 0px) !important;
		}

		.uni-swiper-slide-frame {
			transform: translate3d(0px, 0px, 0px) !important;
		}

		&__item {
			position: absolute;
			width: 100%;
			height: 100%;
			transform-origin: left center;
			transform: translate3d(100%, 0px, 0px) scale(1) !important;
			transition: transform 0.25s ease-in-out;
			z-index: 1;

			&--0 {
				transform: translate3d(0%, 0px, 0px) scale(1) !important;
				z-index: 4;
			}

			&--1 {
				transform: translate3d(13%, 0px, 0px) scale(0.9) !important;
				z-index: 3;
			}

			&--2 {
				transform: translate3d(26%, 0px, 0px) scale(0.8) !important;
				z-index: 2;
			}
		}

		&__content {
			border-radius: 40rpx;
			width: 640rpx;
			height: 500rpx;
			overflow: hidden;
		}

		&__image {
			width: 100%;
			height: 100%;
		}
	}
}

/* 文章内容 end*/

/* 间隔线 start*/
.tn-strip-bottom {
	width: 100%;
	border-bottom: 20rpx solid rgba(241, 241, 241, 0.8);
}

/* 间隔线 end*/

/* 广告内容 start */
.ad-image {
	width: 80rpx;
	height: 80rpx;
	position: relative;
}

.ad-pic {
	background-size: cover;
	background-repeat: no-repeat;
	// background-attachment:fixed;
	background-position: top;
	border-radius: 20%;
}

/* 自定义导航栏内容 end */

/* 全屏轮播  start*/

.card-swiper {
	height: 100vh !important;
}

.card-swiper swiper-item {
	width: 750rpx !important;
	left: 0rpx;
	box-sizing: border-box;
	overflow: initial;
}

.card-swiper swiper-item .swiper-item {
	width: 100%;
	display: block;
	height: 100vh;
	border-radius: 0rpx;
	transform: scale(1);
	transition: all 0.2s ease-in 0s;
	overflow: hidden;
}

.card-swiper swiper-item.cur .swiper-item {
	transform: none;
	transition: all 0.2s ease-in 0s;
}

.card-swiper swiper-item .swiper-item-png {
	width: 100%;
	display: block;
	border-radius: 0rpx;
	transform: translate(1040rpx, 20rpx) scale(0.5, 0.5);
	transition: all 0.6s ease 0s;
	// overflow: hidden;
}

.card-swiper swiper-item.cur .swiper-item-png {
	width: 900rpx;
	transform: translate(-80rpx, 0rpx) scale(1, 1);
	transition: all 0.6s ease 0s;
}

.image-banner {
	display: flex;
	align-items: center;
	justify-content: center;
}

.image-banner image {
	width: 100%;
}

.live {
	position: relative;
	height: 100vh;
	overflow: hidden;
}

.video {
	height: 100vh;
	width: 100%;
}

.content {
	// background: rgba(0, 0, 0, 0.6);
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 999;
	transition: left 0.3s ease;
}

.hide {
	left: 100vw;
}

.header {
	position: fixed;
	top: 0rpx;
	left: 20rpx;
	right: 0;
	min-width: 750rpx;

	.top {
		display: flex;
		align-items: center;
		justify-content: space-between;
		width: 100%;

		.search {
			margin-right: 50rpx;
		}
	}

	.close {
		margin-right: 20rpx;
	}

	.user {
		display: flex;
		align-items: center;
		background: rgba(0, 0, 0, 0.15);
		border-radius: 12rpx;
		padding: 12rpx;
		// padding: 6rpx;
		// overflow: hidden;

		.avatar {
			height: 42rpx;
			width: 42rpx;
			background-size: cover;
			/* 背景图覆盖整个容器 */
			// clip-path: circle(50% at center); /* 使用clip-path制作圆形 */
			overflow: hidden;
		}

		.username {
			color: #fff;
			font-size: 26rpx;
			font-weight: 500;
			align-self: flex-start;
		}

		.desc {
			color: #ccc;
			font-size: 22rpx;
			align-self: flex-start;
		}

		.userinfo {
			display: flex;
			flex-direction: column;
			// align-items: center;
			padding: 0 10rpx;
			color: #fff;

			.username,
			.company-name {
				padding-left: 10rpx;
				font-size: 24rpx;
				font-weight: 500;
				align-self: flex-start;
			}

			.desc {
				color: #ccc;
				font-size: 22rpx;
				align-self: flex-start;
			}
		}

		.follow {
			// font-size: 22rpx;
			// background: linear-gradient(to right, #FF4656, #FE2B8C);
			// color: #fff;
			// width: 90rpx;
			// border-radius: 100rpx;
			// height: 60rpx;
			// line-height: 60rpx;
			// justify-content: center;
		}
	}

	.search-icon {
		margin-right: 96rpx;
	}

	.onlineuser {
		.avatar {
			position: relative;

			text {
				width: 72rpx;
				height: 30rpx;
				line-height: 30rpx;
				font-size: 16rpx;
				text-align: center;
				position: absolute;
				left: 2rpx;
				bottom: 0px;
				font-weight: 500;
				color: #fff;
			}

			image {
				width: 74rpx;
				height: 74rpx;
				border-radius: 100%;
				margin-right: 20rpx;
			}

			&:first-child {
				&::after {
					content: " ";
					width: 74rpx;
					height: 74rpx;
					// background-image: url(@/static/icons/shouhu.webp);
					background-size: 74rpx 74rpx;
					background-repeat: no-repeat;
					background-position: center center;
					display: block;
					position: absolute;
					left: 0px;
					top: 0px;
					z-index: 1;
				}

				text {
					border: none;
					background-image: url(https://vr0.6rooms.com/tao/i/n7/2449060832f8a39fe6772f87de1bef9d.png);
					background-size: 100% 100%;
				}
			}
		}
	}

	.title-list {
		margin-top: 10rpx;

		.title-item {
			background: rgba(0, 0, 0, 0.3);
			border-radius: 100rpx;
			margin-right: 20rpx;
			padding: 5rpx 15rpx;

			.text {
				font-size: 24rpx;
				color: #fff;
				margin-left: 2rpx;
			}
		}
	}
}

// 亲密度
.intimacy-box {
	background: rgba(0, 0, 0, 0.15);
	width: 169.03rpx;
	height: 49.62rpx;
	display: flex;
	align-items: center;
	margin-top: 20rpx;
	border-radius: 116rpx;
	padding: 10px 8px;
	color: #ffffff;
	font-size: 19rpx;
	font-weight: 400;

	.intimacy-item-icon {
		width: 34.35rpx;
		height: 34.35rpx;
		margin-right: 10rpx;
	}

	.intimacy-item-title {
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: center;
		padding-bottom: 4rpx;

		.intimacy-item-value {
			padding-left: 10rpx;
		}
	}
}

.more-content {
	width: 102rpx;
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 40rpx;
	margin-top: 30rpx;

	.more-grid {
		position: relative;
		display: grid;
		grid-template-columns: repeat(4, 1fr);
		gap: 40rpx;
		z-index: 9999999;
	}

	.more-item {
		display: flex;
		flex-direction: column;
		align-items: center;

		.more-icon-bg {
			width: 82rpx;
			height: 82rpx;
			margin-bottom: 15rpx;
			background: rgba(130, 128, 128, 0.5);
			border-radius: 27rpx;
			display: flex;
			align-items: center;
			justify-content: center;

			.more-icon {
				width: 45.8rpx;
				height: 45.8rpx;
			}
		}

		.more-text {
			font-size: 20rpx;
			color: #fff;
		}
	}
}



/* 轮播指示点 start*/
.indication {
	z-index: 9999;
	width: 100%;
	height: 36rpx;
	position: fixed;
	// display:flex;
	display: block;
	flex-direction: row;
	align-items: center;
	justify-content: center;
}

.spot {
	background-color: #000;
	opacity: 0.3;
	width: 10rpx;
	height: 10rpx;
	border-radius: 20rpx;
	margin: 20rpx 0 !important;
	left: 95vw;
	top: -60vh;
	position: relative;
}

.spot.active {
	opacity: 0.6;
	height: 30rpx;
	background-color: #000;
}

/* 资讯主图 start*/
.image-article {
	border-radius: 8rpx;
	border: 1rpx solid #f8f7f8;
	width: 200rpx;
	height: 200rpx;
	position: relative;
}

.image-pic {
	background-size: cover;
	background-repeat: no-repeat;
	// background-attachment:fixed;
	background-position: top;
	border-radius: 10rpx;
}

.article-shadow {
	border-radius: 15rpx;
	box-shadow: 0rpx 0rpx 50rpx 0rpx rgba(0, 0, 0, 0.07);
}

/* 文字截取*/
.clamp-text-1 {
	-webkit-line-clamp: 1;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	text-overflow: ellipsis;
	overflow: hidden;
}

.clamp-text-2 {
	-webkit-line-clamp: 2;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	text-overflow: ellipsis;
	overflow: hidden;
}

/* 标签内容 start*/
.tn-tag-content {
	&__item {
		display: inline-block;
		line-height: 35rpx;
		padding: 5rpx 25rpx;

		&--prefix {
			padding-right: 10rpx;
		}
	}
}

/* 图标容器9 start */
.icon9 {
	&__item {
		width: 30%;
		background-color: #ffffff;
		border-radius: 10rpx;
		padding: 30rpx;
		margin: 20rpx 10rpx;
		transform: scale(1);
		transition: transform 0.3s linear;
		transform-origin: center center;

		&--icon {
			width: 110rpx;
			height: 110rpx;
			font-size: 65rpx;
			border-radius: 50%;
			margin: 20rpx 40rpx;
			position: relative;
			z-index: 1;

			&::after {
				content: " ";
				position: absolute;
				z-index: -1;
				width: 100%;
				height: 100%;
				left: 0;
				bottom: 0;
				border-radius: inherit;
				opacity: 1;
				transform: scale(1, 1);
				background-size: 100% 100%;
				background-image: url(https://resource.tuniaokj.com/images/cool_bg_image/icon_bg2.png);
			}
		}
	}
}

/* 悬浮 */
.tnxuanfu {
	animation: suspension 3s ease-in-out infinite;
}

@keyframes suspension {

	0%,
	100% {
		transform: translateY(0);
	}

	50% {
		transform: translateY(-0.8rem);
	}
}

/* 悬浮按钮 */
.button-shop {
	width: 120rpx;
	height: 120rpx;
	display: flex;
	flex-direction: row;
	position: fixed;
	/* bottom:200rpx;
      right: 20rpx; */
	left: 5rpx;
	top: 5rpx;
	z-index: 1001;
	border-radius: 100px;
	opacity: 0.9;
}

/* 按钮 */
.edit {
	bottom: 300rpx;
	right: 50%;
	position: fixed;
	z-index: 9999;
}

/* 底部 start*/
.footerfixed {
	position: fixed;
	width: 100%;
	bottom: env(safe-area-inset-bottom);
	z-index: 9999;
	background-color: rgba(255, 255, 255, 0.5);
	box-shadow: 0rpx 0rpx 30rpx 0rpx rgba(0, 0, 0, 0.07);
}

.tabbar {
	align-items: center;
	// min-height: 130rpx;
	padding: 0;
	height: calc(170rpx + env(safe-area-inset-bottom) / 2);
	padding-bottom: env(safe-area-inset-bottom);
	padding-left: 10rpx;
	padding-right: 10rpx;
}

/* 毛玻璃*/
.dd-glass {
	width: 100%;
	backdrop-filter: blur(20rpx);
	-webkit-backdrop-filter: blur(20rpx);
}

/* 头像*/
.avatar-all {
	width: 60rpx;
	height: 60rpx;
	border: 4rpx solid rgba(255, 255, 255, 0.05);
	border-radius: 50%;
	overflow: hidden;
	box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15);
}

/* 内容*/
.topic {
	position: relative;
	height: 100%;
	z-index: 1;
	margin-bottom: 120rpx;

	/* 表单信息 start */
	&__info {
		margin: 0 50rpx;
		margin-top: 105rpx;
		padding: 30rpx 51rpx;
		border-radius: 20rpx;
		background-color: rgba(255, 255, 255, 1);
		border: 2rpx solid rgba(255, 255, 255, 0.1);
		box-shadow: 0rpx 10rpx 50rpx 0rpx rgba(0, 3, 72, 0.1);

		&__item {
			&__input {
				width: 400rpx;
				height: 60rpx;
				border: 1rpx solid #c6d1d8;
				border-radius: 39rpx;

				&__left-icon {
					width: 10%;
					font-size: 44rpx;
					margin-left: 20rpx;
					margin-right: 5rpx;
					color: #000000;
				}

				&__content {
					width: 80%;
					padding-left: 10rpx;

					&--verify-code {
						width: 56%;
					}

					input {
						font-size: 30rpx;
						color: #000000;
						// letter-spacing: 0.1em;
					}
				}

				&__right-icon {
					width: 10%;
					font-size: 34rpx;
					margin-right: 20rpx;
					color: #78909c;
				}

				&__right-verify-code {
					width: 34%;
					margin-right: 20rpx;
				}
			}

			&__button {
				width: 100%;
				height: 60rpx;
				text-align: center;
				font-size: 31rpx;
				font-weight: bold;
				line-height: 77rpx;
				// text-indent: 1em;
				border-radius: 100rpx;
				color: #ffffff;
				background-color: rgba(255, 255, 255, 0.2);
				// border: 2rpx solid #FFFFFF;
			}

			&__sure {
				height: 60rpx;
				width: 140rpx;
			}
		}
	}

	/* 表单信息 end */

	/* 内容 end */
}

::v-deep.input-placeholder {
	font-size: 36rpx;
	color: #000000;
}

::v-deep.uni-input-input {
	margin-top: 10px;
}

.pa,
.pa0 {
	position: absolute;
}

.pa0 {
	left: 0;
	top: 0;
}

.bg0 {
	width: 100rpx;
	height: 100rpx;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
}

.bg1 {
	width: 100%;
	height: 100%;
}

.hx-box {
	top: 50%;
	left: 50%;
	width: 100rpx;
	height: 100rpx;
	transform-style: preserve-3d;
	transform: translate(-50%, -50%) rotateY(75deg) rotateZ(10deg);
}

.hx-box .pr {
	width: 100rpx;
	height: 100rpx;
	transform-style: preserve-3d;
	animation: hxz 20s linear infinite;
}

@keyframes hxz {
	0% {
		transform: rotateX(0deg);
	}

	100% {
		transform: rotateX(-360deg);
	}
}

.hx-box .pr .pa0 {
	width: 100rpx;
	height: 100rpx;
	/* border: 4px solid #5ec0ff; */
	border-radius: 1000px;
}

.hx-box .pr .pa0 .span {
	display: block;
	width: 100%;
	height: 100%;
	background: url(https://resource.tuniaokj.com/images/cool_bg_image/arc4.png) no-repeat center center;
	background-size: 100% 100%;
	animation: hx 4s linear infinite;
}

@keyframes hx {
	to {
		transform: rotate(360deg);
	}
}

.hx-k1 {
	transform: rotateX(-60deg) rotateZ(-60deg);
}

.hx-k2 {
	transform: rotateX(-30deg) rotateZ(-30deg);
}

.hx-k3 {
	transform: rotateX(0deg) rotateZ(0deg);
}

.hx-k4 {
	transform: rotateX(30deg) rotateZ(30deg);
}

.hx-k5 {
	transform: rotateX(60deg) rotateZ(60deg);
}

.hx-k6 {
	transform: rotateX(90deg) rotateZ(90deg);
}

/* 用户头像 start */
.logo-image2 {
	width: 110rpx;
	height: 110rpx;
	position: relative;
}

.logo-pic2 {
	background-size: cover;
	background-repeat: no-repeat;
	// background-attachment:fixed;
	background-position: top;
	border: 8rpx solid rgba(255, 255, 255, 0.05);
	box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15);
	border-radius: 50%;
	overflow: hidden;
	// background-color: #FFFFFF;
}

/* 内容*/
.reserve {
	width: 100%;
	position: fixed;
	z-index: 99;
}

.message {
	position: relative;
	bottom: 10rpx;
	left: 20rpx;
	right: 20rpx;
	min-width: 750rpx;

	.msg-scroll {
		height: 600rpx;

		&.mask {
			-webkit-mask: -webkit-gradient(linear,
					left 30%,
					left top,
					from(#000),
					to(transparent));
		}

		.msg-item {
			background: rgba(0, 0, 0, 0.3);
			border-radius: 100px;
			max-width: 80%;
			margin-bottom: 10rpx;
			color: #fff;
			font-size: 28rpx;
			padding: 15rpx 20rpx;
			border-radius: 20rpx;
			white-space: pre-wrap;
			align-self: flex-start;
			transition: opacity 0.3s ease;

			image {
				height: 36rpx;
				margin-right: 5rpx;
				vertical-align: middle;
			}

			.username {
				font-weight: 500;
				color: #77c4bc;
			}

			&.system {
				color: #ffffff;
			}
		}
	}
}

.reserve-content {
	background-image: linear-gradient(to bottom,
			rgba(255, 255, 255, 0),
			rgba(255, 255, 255, 0));
	border-radius: 30rpx;
}

/* 悬浮 */
.tnxuanfu {
	animation: suspension 3s ease-in-out infinite;
}

/* 悬浮按钮 */
.button-shop {
	width: 120rpx;
	height: 120rpx;
	display: flex;
	flex-direction: row;
	position: fixed;
	/* bottom:200rpx;
        right: 20rpx; */
	left: 5rpx;
	top: 5rpx;
	z-index: 1001;
	border-radius: 100px;
	opacity: 0.9;
}

/* 按钮 */
.edit {
	bottom: 360rpx;
	right: 50%;
	position: fixed;
	z-index: 9999;
}

/* 标签 */
.blogger {
	&__item {
		padding: 30rpx;
	}

	&__desc {
		line-height: 55rpx;

		&__label {
			padding: 0 20rpx;
			margin: 0rpx 18rpx 0 0;

			&--prefix {
				color: #00ffc8;
				padding-right: 10rpx;
			}
		}
	}
}

/* 文字截取*/
.clamp-text-1 {
	-webkit-line-clamp: 1;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	text-overflow: ellipsis;
	overflow: hidden;
}

.clamp-text-2 {
	-webkit-line-clamp: 2;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	text-overflow: ellipsis;
	overflow: hidden;
}

/* 毛玻璃*/
.dd-glass {
	width: 100%;
	backdrop-filter: blur(10rpx);
	-webkit-backdrop-filter: blur(10rpx);
}

/* 毛玻璃*/
.dd-glass2 {
	// width: 100%;
	backdrop-filter: blur(8rpx);
	-webkit-backdrop-filter: blur(8rpx);
}

/* 用户头像 start */
.user-image {
	width: 70rpx;
	height: 70rpx;
	position: relative;
}

.user-pic {
	background-size: cover;
	background-repeat: no-repeat;
	// background-attachment:fixed;
	background-position: top;
	border-radius: 100rpx;
	overflow: hidden;
	background-color: #ffffff;
}

/* 底部悬浮按钮 start*/
.tn-tabbar-height {
	min-height: 120rpx;
	height: calc(140rpx + env(safe-area-inset-bottom) / 2);
}

.tn-footerfixed {
	position: fixed;
	// background-color: rgba(255,255,255,0.5);
	bottom: 4%;
	width: 100%;
	transition: all 0.25s ease-out;
	z-index: 100;
}

.tn-footerfixed.swiper-fixed {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 240rpx;
	right: 40rpx !important;
	bottom: 25rpx !important;
	left: auto !important;
	background: #fff;

	.footer-main-text {
		padding-left: 0px !important;

		.recording-text {
			color: #000;
			font-size: 16px;
		}
	}

	.bar {
		background: #000;
	}
}

.custom-footer {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 4%;
	z-index: 100;
	display: flex;
	align-items: center;
	justify-content: space-between;
	background: rgba(130, 128, 128, 0.5);
	color: #fff;
	border-radius: 18rpx;
	width: 703.85rpx;
	height: 85rpx;
	margin: 0 auto;
	padding: 0 18rpx;
}

.footer-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	margin: 0 8rpx;
}

.footer-icon,
.footer-icon-add {
	width: 46.66rpx;
	height: 46.66rpx;
	display: block;
}

.footer-icon-add {
	margin-right: 30rpx;
}

.footer-main-text {
	flex: 1;
	text-align: center;
	color: #bfc2c7;
	//padding-left: 30rpx;
	font-size: 32rpx;
	font-weight: bold;
	letter-spacing: 2rpx;
	opacity: 0.7;
}

.footer-btn.fullscreen {
	margin-left: 0;
}

.footer-main-input-wrap {
	flex: 1;
	display: flex;
	align-items: center;
	height: 56rpx;
	margin-left: 12rpx;
	margin-right: 0;
	min-width: 0;

	.tn-padding-xs {
		width: 80px !important;
		border: none !important;
		box-shadow: none !important;
		background: transparent;
		color: #fff !important;
	}
}

.footer-main-input {
	width: 100%;
	height: 100%;
	border: none;
	outline: none;
	background: transparent;
	color: #fff;
	font-size: 31rpx;
	padding: 0;
	text-align: left;
	box-sizing: border-box;
}

.recording-bar-outer {
	width: 100%;
	height: 85rpx;
	border-radius: 24rpx;
	display: flex;
	align-items: center;
	justify-content: center;
}

.recording-bar-inner {
	width: 240rpx;
	height: 60rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	background: transparent;
}

.recording-bar {
	width: 180rpx;
	height: 36rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8rpx;

	.bar {
		width: 8rpx;
		background: #fff;
		border-radius: 4rpx;
		height: 24rpx; // 默认高度
		transform-origin: center bottom; // 从底部中心缩放

		// 使用CSS动画，性能更好
		animation: barWave 1.5s ease-in-out infinite;
		animation-delay: var(--delay); // 每个bar有不同的延迟
		animation-play-state: paused; // 默认暂停

		// 添加硬件加速
		will-change: transform, height;
		backface-visibility: hidden;
		perspective: 1000px;
	}

	// 当录音时启动动画
	&.animating .bar {
		animation-play-state: running;
	}
}

// 音频条波动动画
@keyframes barWave {

	0%,
	100% {
		height: 24rpx;
		transform: scaleY(1);
		opacity: 0.8;
	}

	25% {
		height: 40rpx;
		transform: scaleY(1.2);
		opacity: 1;
	}

	50% {
		height: 32rpx;
		transform: scaleY(1.1);
		opacity: 0.9;
	}

	75% {
		height: 48rpx;
		transform: scaleY(1.3);
		opacity: 1;
	}
}

// 为不同位置的bar添加不同的动画效果
.recording-bar .bar:nth-child(odd) {
	animation-duration: 1.2s; // 奇数bar稍快
}

.recording-bar .bar:nth-child(even) {
	animation-duration: 1.8s; // 偶数bar稍慢
}

// 添加渐变效果，让动画更自然
.recording-bar .bar {
	background: linear-gradient(to top, #fff, #e0e0e0);
	box-shadow: 0 0 8rpx rgba(255, 255, 255, 0.3);
}

.ai-generated-tip {
	width: 100%;
	text-align: center;
	// color: #B2B2B2;
	color: #fff;
	font-size: 26rpx;
	margin-bottom: 18rpx;
	margin-top: 0;
	font-weight: 500;
	letter-spacing: 1rpx;
}

/* 相册 start*/
.slideshow {
	top: 0;
	position: absolute;
	width: 100vw;
	height: 100vh;
	// overflow: hidden;
	background: linear-gradient(to bottom, #414b8c, #1c1d21);
	z-index: 111;
}

::v-deep .uni-video-container {
	height: 100% !important;
	/* 使用!important确保优先级更高 */
	min-height: 100% !important;
}

::v-deep .uni-video-video {
	/* 使用!important确保优先级更高 */
	object-fit: contain !important;
	height: auto !important;
}

.video-container {
	position: fixed;
	width: 100%;
	height: 100vh;
	overflow: hidden;
	z-index: 100;
}

.slideshow2 {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	min-height: 100%;
	object-fit: cover;
	z-index: 100;
}

.gradient-overlay {
	position: absolute;
	z-index: 100;
	pointer-events: none;
	/* 允许点击穿透到视频 */
}

// 黑色

.gradient-overlay.bottom {
	bottom: 0vh;
	left: 0;
	width: 100%;
	// height: 45vh;
	// background: linear-gradient(to top,
	// 		rgba(0, 0, 0, 1) 0%,
	// 		rgba(0, 0, 0, 1) 50%,
	// 		transparent 100%);
}

.content-overlay {
	position: absolute;
	bottom: 10vh;
	left: 50%;
	transform: translateX(-50%);
	color: rgba(255, 255, 255, 0.7);
	font-size: 24rpx;
	z-index: 102;
}

.slideshow-image {
	position: absolute;
	width: 100vw;
	height: 100vh;
}

@-webkit-keyframes kenburns-1 {
	0% {
		opacity: 1;
		transform: scale(1.2);
	}

	1.5625% {
		opacity: 1;
	}

	23.4375% {
		opacity: 1;
	}

	26.5625% {
		opacity: 0;
		transform: scale(1);
	}

	100% {
		opacity: 0;
		transform: scale(1.2);
	}

	98.4375% {
		opacity: 0;
		transform: scale(1.2117647059);
	}

	100% {
		opacity: 1;
	}
}

@keyframes kenburns-1 {
	0% {
		opacity: 1;
		transform: scale(1.2);
	}

	1.5625% {
		opacity: 1;
	}

	23.4375% {
		opacity: 1;
	}

	26.5625% {
		opacity: 0;
		transform: scale(1);
	}

	100% {
		opacity: 0;
		transform: scale(1.2);
	}

	98.4375% {
		opacity: 0;
		transform: scale(1.2117647059);
	}

	100% {
		opacity: 1;
	}
}

@-webkit-keyframes kenburns-2 {
	23.4375% {
		opacity: 1;
		transform: scale(1.2);
	}

	26.5625% {
		opacity: 1;
	}

	48.4375% {
		opacity: 1;
	}

	51.5625% {
		opacity: 0;
		transform: scale(1);
	}

	100% {
		opacity: 0;
		transform: scale(1.2);
	}
}

@keyframes kenburns-2 {
	23.4375% {
		opacity: 1;
		transform: scale(1.2);
	}

	26.5625% {
		opacity: 1;
	}

	48.4375% {
		opacity: 1;
	}

	51.5625% {
		opacity: 0;
		transform: scale(1);
	}

	100% {
		opacity: 0;
		transform: scale(1.2);
	}
}

@-webkit-keyframes kenburns-3 {
	48.4375% {
		opacity: 1;
		transform: scale(1.2);
	}

	51.5625% {
		opacity: 1;
	}

	73.4375% {
		opacity: 1;
	}

	76.5625% {
		opacity: 0;
		transform: scale(1);
	}

	100% {
		opacity: 0;
		transform: scale(1.2);
	}
}

@keyframes kenburns-3 {
	48.4375% {
		opacity: 1;
		transform: scale(1.2);
	}

	51.5625% {
		opacity: 1;
	}

	73.4375% {
		opacity: 1;
	}

	76.5625% {
		opacity: 0;
		transform: scale(1);
	}

	100% {
		opacity: 0;
		transform: scale(1.2);
	}
}

@-webkit-keyframes kenburns-4 {
	73.4375% {
		opacity: 1;
		transform: scale(1.2);
	}

	76.5625% {
		opacity: 1;
	}

	98.4375% {
		opacity: 1;
	}

	100% {
		opacity: 0;
		transform: scale(1);
	}
}

@keyframes kenburns-4 {
	73.4375% {
		opacity: 1;
		transform: scale(1.2);
	}

	76.5625% {
		opacity: 1;
	}

	98.4375% {
		opacity: 1;
	}

	100% {
		opacity: 0;
		transform: scale(1);
	}
}

/* 相册 end*/

.tn-tabbar-height {
	min-height: 100rpx;
	height: calc(120rpx + env(safe-area-inset-bottom) / 2);
}

/* 用户头像 start */
.logo-image {
	width: 80rpx;
	height: 80rpx;
	position: relative;
}

.logo-pic {
	background-size: cover;
	background-repeat: no-repeat;
	// background-attachment:fixed;
	background-position: top;
	// box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15);
	border-radius: 50%;
	// overflow: hidden;
	// background-color: #FFFFFF;
}

.bg-img-cont {
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	height: 260rpx;
	width: 55vw;
	margin: 10rpx 0 0 0;
	border-radius: 12rpx;
}

/* 聊天*/
.tnchat1 {
	border-style: solid;
	border-width: 71rpx;
	border-image-source: url(https://cdn.nlark.com/yuque/0/2022/png/280373/1656388937089-assets/web-upload/9d92dfd6-3486-4be9-a933-0ae160bdfc86.png);
	border-image-slice: 71 71 71 71 fill;
	border-image-repeat: repeat;
	word-break: break-word;
	width: fit-content;
}

.tnchat2 {
	border-style: solid;
	border-width: 26rpx 43rpx;
	border-image-source: url(https://cdn.nlark.com/yuque/0/2022/png/280373/1656471916508-assets/web-upload/e2305ffa-d1c7-435c-adae-2b3f0bc0da41.png);
	border-image-slice: 26 43 26 43 fill;
	border-image-repeat: repeat;
	word-break: break-word;
	width: fit-content;
}

.tnchat3 {
	border-style: solid;
	border-width: 26rpx 43rpx;
	border-image-source: url(https://cdn.nlark.com/yuque/0/2022/png/280373/1656562395500-assets/web-upload/2662c10c-061b-403d-9289-1165d9ee9e7b.png);
	border-image-slice: 26 43 26 43 fill;
	border-image-repeat: repeat;
	word-break: break-word;
	width: fit-content;
}

.tnchat4 {
	border-style: solid;
	border-width: 26rpx 43rpx;
	border-image-source: url(https://cdn.nlark.com/yuque/0/2022/png/280373/1656562336904-assets/web-upload/ad050d7f-3bdd-4de5-9e67-500f778b20e4.png);
	border-image-slice: 26 43 26 43 fill;
	border-image-repeat: repeat;
	word-break: break-word;
	width: fit-content;
}

.tnchat5 {
	border-style: solid;
	border-width: 26rpx 43rpx;
	border-image-source: url(https://cdn.nlark.com/yuque/0/2022/png/280373/1656562607434-assets/web-upload/cf008270-2a2c-4fac-82b1-b558d8a92230.png);
	border-image-slice: 26 43 26 43 fill;
	border-image-repeat: repeat;
	word-break: break-word;
	width: fit-content;
}

.tnchat6 {
	border-style: solid;
	border-width: 26rpx 43rpx;
	border-image-source: url(https://cdn.nlark.com/yuque/0/2022/png/280373/1656598070402-assets/web-upload/e123a1e3-6235-4d39-81d5-33d221d7a960.png);
	border-image-slice: 26 43 26 43 fill;
	border-image-repeat: repeat;
	word-break: break-word;
	width: fit-content;
}

.tnchat7 {
	border-style: solid;
	border-width: 26rpx 43rpx;
	border-image-source: url(https://cdn.nlark.com/yuque/0/2022/png/280373/1656602660855-assets/web-upload/9c698bba-af80-47bf-9ee4-3a78e0288fc4.png);
	border-image-slice: 26 43 26 43 fill;
	border-image-repeat: repeat;
	word-break: break-word;
	width: fit-content;
}

.container {
	height: 100vh;
	overflow: hidden;
}

/* #ifdef H5 */
.container {
	height: calc(100vh);
}

/* #endif */

.map {
	width: 60%;
	height: 300upx;
	background-color: #fff !important;

	&::before {
		border-right: 30upx solid #fff !important;
	}

	.title {
		height: 80upx;
		font-size: 28upx;
		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
	}

	.box {
		width: 100%;
		height: 170upx;
		margin-top: 10upx;
	}
}

.file {
	padding: 30upx 20upx;

	.list {
		overflow: hidden;
		padding-left: 10upx;
		justify-content: flex-start;
	}

	.item {
		width: 110upx;
		height: 110upx;
		border-radius: 10upx;
		padding-left: 10upx;
		justify-content: center;
		align-items: center;
		background-color: #fff;

		.icon {
			padding-left: 25upx;
			// justify-content: center;
			// align-items: center;
			width: 70upx;
		}

		.text {
			padding-left: 3upx;
			justify-content: center;
			align-items: center;
			font-size: 24upx;
			margin-top: 4upx;
		}
	}
}

.oper {
	width: 98%;
	height: 100upx;
	background: #ffffff;
	border-radius: 10px;
	opacity: 0.8;
	// border-top: 2upx solid #EEE;
	// border-bottom: 2upx solid #EEE;

	.input {
		height: 78upx;
		line-height: 78upx;
		padding: 9px 20upx;
		font-size: 33upx;
		border-radius: 10upx;
		background-color: #fff;
		width: 100%;
	}

	.icon {
		margin-top: 10px;
		width: 60upx;
		height: 60upx;
		// padding-left: 20upx;
	}

	.btn {
		margin-top: 10px;
		color: #fff;
		width: 120upx;
		height: 65upx;
		font-size: 33upx;
		// line-height: 50upx;
		text-align: center;
		align-items: center;
		border-radius: 10upx;
		background-color: #2ba245;
	}
}

// 图片预览样式
.image-preview {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: #100d05;
	z-index: 999999999;
	display: flex;
	align-items: center;
	justify-content: center;

	.preview-image {
		width: 100%;
		height: 100%;
	}
}

/* #ifdef H5 */
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&display=swap");

/* #endif */
.scroll {
	width: 100%;
	overflow-y: auto;
	transition: all 0.1s ease;
	height: calc(100vh - 88upx - 110upx - var(--status-bar-height));
	mask-image: linear-gradient(to top,
			black 40%,
			rgba(0, 0, 0, 0.9) 50%,
			rgba(0, 0, 0, 0.7) 70%,
			rgba(0, 0, 0, 0.5) 80%,
			transparent 90%);
	-webkit-mask-image: linear-gradient(to top,
			black 40%,
			rgba(0, 0, 0, 0.9) 50%,
			rgba(0, 0, 0, 0.7) 70%,
			rgba(0, 0, 0, 0.5) 80%,
			transparent 90%);
	/* #ifdef MP-WEIXIN */
	height: calc(100vh - 88upx - var(--status-bar-height));
	/* #endif */
	/* #ifdef H5 */
	height: calc(40vh - 88upx - 110upx - var(--status-bar-height));

	/* #endif */
	&.justify-end {
		::v-deep .uni-scroll-view-content {
			display: flex;
			flex-direction: column;
			justify-content: flex-end;
		}

	}

	.item-space {
		height: 30upx;
	}

	.message-image {
		.image-content {
			max-width: 180rpx; // 限制最大宽度，让图片更小
			max-height: 300rpx; // 限制最大高度
			border-radius: 8rpx;
			object-fit: contain; // 保持图片完整显示，不裁剪
		}

		overflow: hidden; // 隐藏超出圆角部分
	}

	.reserve-tips {
		width: 225rpx;
		height: 62rpx;
		background: rgba(130, 128, 128, 0.5);
		border-radius: 12rpx;
		backdrop-filter: blur(12px);
		color: #fff;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 24rpx;
		margin: 0 auto;
		margin-bottom: 20rpx;
	}

	.time {
		color: #666;
		font-size: 24upx;
		text-align: center;
		margin-bottom: 50upx;
	}

	.cancel {
		width: 100%;
		height: 40upx;
		text-align: center;
		margin-bottom: 50upx;

		.text {
			color: #999;
			font-size: 24upx;
		}
	}

	.item {
		margin: 0 0 10upx;
		align-items: flex-start;
		justify-content: flex-start;

		.face {
			width: 70upx;
			height: 70upx;
			border-radius: 10upx;
		}

		.content {
			background: linear-gradient(180deg,
					rgba(255, 255, 255, 0) 0%,
					#ffffff 100%);
			color: #ffffff;
			font-size: 32upx;
			min-height: 80upx;
			border-radius: 10upx;
			padding: 26upx;
			background-color: transparent;
			word-break: break-all;
			word-wrap: break-word;
			max-width: calc(100% - 100upx);
			position: relative;
			/* #ifdef H5 */
			font-family: "Noto Sans SC", sans-serif;
			/* #endif */
		}

		.ctxt {
			font-family: PingFangSC, PingFang SC;
			font-weight: 400;
			font-size: 14px;
			color: #ffffff;
			line-height: 22px;
			text-align: left;
			font-style: normal;
			opacity: 1;
			/* 确保文字不透明 */
		}

		&.left {
			.face {
				margin-top: 5rpx;
				margin-left: -12upx;
				margin-right: -12upx;
			}

			.content {
				background: #414b8c;
				background-color: rgba(65, 75, 140, 0.4);
				border-radius: 10px;
				// opacity: 0.4;
				// background-color: transparent;
				/* #ifdef H5 */
				font-family: "Noto Sans SC", sans-serif;
				/* #endif */
			}

			.content::before {
				left: -60upx;
			}
		}

		&.right {
			flex-direction: row-reverse;

			.face {
				margin-top: 5rpx;
				margin-right: -12upx;
				margin-left: -12upx;
			}

			.content {
				background: #000;
				background-color: rgba(0, 0, 0, 0.4);
				border-radius: 10px;
				// opacity: 0.4;
				// background-color: transparent;
				/* #ifdef H5 */
				font-family: "Noto Sans SC", sans-serif;
				/* #endif */
			}
		}
	}

	.gcontainer {
		display: flex;
		flex-wrap: wrap;
		/* 允许换行 */
		gap: 10px;
		/* 元素间距（可选） */
	}

	.gitem {
		flex-basis: calc(33.33% - 10px);
		/* 每行3个，减去间隙 */
		/* 或者直接设置固定宽度（根据需求调整） */
		/* width: 30%; */
	}

	.logoimg {
		position: absolute;
		top: 155rpx;
		z-index: 10;
	}

	.loader {
		z-index: 222;
		position: absolute;
		top: 45%;
		left: 50%;
		width: 80px;
		height: 80px;
		transform: translate(-50%, -50%);
		border-radius: 50%;
		background: linear-gradient(#f07e6e, #84cdfa, #5ad1cd);
		animation: animate 1.2s linear infinite;
	}

	@keyframes animate {
		0% {
			transform: rotate(0deg);
		}

		100% {
			transform: rotate(360deg);
		}
	}

	.loader:after {
		content: "";
		position: absolute;
		top: 10px;
		left: 10px;
		right: 10px;
		bottom: 10px;
		background: #f1f1f1;
		border: solid white 10px;
		border-radius: 50%;
	}

	#bottom {
		height: 60upx;
		border-bottom: 800upx;
	}
}

// 顶部banner
.banner {
	width: 100vh;
	height: 100vw;
	left: -58.3%;
	bottom: 27vh;
	position: fixed;
	// bottom: 18vh;
	// left: 50%;
	transform: translateX(-80%);
	overflow: hidden;
	z-index: 1;
	border-radius: 24rpx;
	overflow: hidden;
	transform: rotate(90deg);
}

.banner .swiper-item {
	width: 100vh;
	height: 100vw;
	// transform: rotate(90deg);
}

.banner-image {
	width: 100vh;
	height: 100vw;
	object-fit: cover;
	display: block;
	border-radius: 0;
	// transform: rotate(90deg);
}

// 顶部banner
.banner2 {
	width: 95vw;
	height: 257px;
	position: fixed;
	bottom: 15vh;
	left: 50%;
	transform: translateX(-50%);
	overflow: hidden;
	z-index: 9999;
	border-radius: 15rpx;
	overflow: hidden;
}

.banner2 .swiper-item {
	width: 95vw;
	height: auto;
	/* 改为自适应高度 */
}

.banner2-image {
	width: 95vw;
	height: auto;
	/* 改为自适应高度 */
	object-fit: contain;
	/* 确保图片完整显示 */
	display: block;
	border-radius: 0;
	max-height: 45vh;
	/* 防止图片过大 */
}

/* 右上角图标 */
.top-right-icon-wrapper {
	position: fixed;
	top: 95rpx;
	right: 16px;
	z-index: 990;
	display: flex;
	flex-direction: row;
	gap: 17px;
}

.top-right-icon {
	display: flex;
	justify-content: center;
	align-items: center;
}

/* 右侧功能菜单 */
.right-menu-container {
	position: fixed;
	top: 97px;
	right: 5px;
	z-index: 990;
	display: flex;
	flex-direction: column;
	// background: rgba(0, 0, 0, 0.5);
	border-radius: 11rpx;
	padding: 4px 0;
	// padding: 15rpx 10rpx;
	// box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
	transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
	transform: scaleY(1);
	transform-origin: top;
	opacity: 1;
	visibility: visible;
	// max-height: 850rpx;
	// overflow: hidden;
}

.right-menu-container.menu-hidden {
	transform: scaleY(0);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	max-height: 0;
}

.menu-item {
	width: 60px;
	height: 58px;
	display: flex;
	flex-direction: column;
	align-items: center;
	// padding: 4px;
	// padding: 4rpx 2rpx;
	border-radius: 8rpx;
	transition: all 0.3s ease;
	// margin-bottom: 18px;
	cursor: pointer;
	transform: translateY(0);
	opacity: 1;
	// background: rgba(0, 0, 0, 0.5);
	// box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
	// border-radius: 50%;

	// &.active {
	//   background-color: rgba(65, 75, 140, 0.2);
	// }

	// &:hover {
	//   background-color: rgba(65, 75, 140, 0.1);
	// }

	.menu-icon {
		width: 50rpx;
		height: 50rpx;
		margin-bottom: 8rpx;
		border-radius: 50%;
		background-color: #f0f0f0;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	.menu-text {
		font-size: 22rpx;
		color: #333;
		font-weight: 500;
	}
}

.right-menu-container.menu-hidden .menu-item {
	transform: translateY(-20rpx);
	opacity: 0;
}

.version-icon {
	background-color: #4caf50;
}

.meeting-icon {
	background-color: #2196f3;
}

.schedule-icon {
	background-color: #ff9800;
}

.slides-icon {
	background-color: #9c27b0;
}

.record-icon {
	background-color: #607d8b;
}

.outfit-icon {
	background-color: #e91e63;
}

.gathering-icon {
	background-color: #3f51b5;
}

.foodluck-icon {
	background-color: #ff5722;
}

.icon-rotated {
	transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
	transform: rotate(90deg) !important;
}

/* 加载背景蒙版层样式 */
.loading-overlay {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-color: rgba(0, 0, 0, 0.5);
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-direction: column;
	color: #fff;
	// backdrop-filter: blur(5px);
}

.loading-spinner {
	width: 60px;
	height: 60px;
	z-index: 1000;
}

/* ==================== 录音遮罩层 ==================== */
.recording-mask {
	position: fixed;
	bottom: 200rpx;
	left: 20rpx;
	width: 280rpx;
	height: 400rpx;
	z-index: 1000;
	border-radius: 20rpx;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}

/* 背景模糊层 */
.recording-mask-bg {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: linear-gradient(135deg,
			rgba(30, 30, 40, 0.95) 0%,
			rgba(20, 20, 30, 0.98) 100%);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
}

/* 中心动画区域 */
.recording-animation-center {
	position: relative;
	width: 280rpx;
	height: 400rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 2;
}

/* 🌊 声波扩散圈 */
.sound-wave {
	position: absolute;
	width: 100rpx;
	height: 100rpx;
	border-radius: 50%;
	border: 4rpx solid rgba(255, 87, 34, 0.6);
	animation: soundWaveExpand 2s ease-out infinite;
}

.wave-1 {
	animation-delay: 0s;
}

.wave-2 {
	animation-delay: 0.6s;
}

.wave-3 {
	animation-delay: 1.2s;
}

@keyframes soundWaveExpand {
	0% {
		width: 140rpx;
		height: 140rpx;
		opacity: 1;
		border-width: 6rpx;
	}

	100% {
		width: 240rpx;
		height: 240rpx;
		opacity: 0;
		border-width: 1rpx;
	}
}

/* 🔴 中心脉动圆 */
.recording-pulse-circle {
	width: 100rpx;
	height: 100rpx;
	border-radius: 50%;
	background: linear-gradient(135deg, #FF5722 0%, #FF7043 100%);
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow:
		0 0 40rpx rgba(255, 87, 34, 0.6),
		0 0 60rpx rgba(255, 87, 34, 0.4),
		0 0 80rpx rgba(255, 87, 34, 0.2);
	animation: pulseScale 1.5s ease-in-out infinite;
	position: relative;
	z-index: 3;
}

.pulse-inner {
	width: 160rpx;
	height: 160rpx;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.15);
	display: flex;
	align-items: center;
	justify-content: center;
	animation: pulseInner 1.5s ease-in-out infinite;
}

.mic-icon {
	width: 80rpx;
	height: 80rpx;
	opacity: 0.9;
}

@keyframes pulseScale {

	0%,
	100% {
		transform: scale(1);
		box-shadow:
			0 0 40rpx rgba(255, 87, 34, 0.6),
			0 0 80rpx rgba(255, 87, 34, 0.4);
	}

	50% {
		transform: scale(1.1);
		box-shadow:
			0 0 60rpx rgba(255, 87, 34, 0.8),
			0 0 120rpx rgba(255, 87, 34, 0.6),
			0 0 180rpx rgba(255, 87, 34, 0.4);
	}
}

@keyframes pulseInner {

	0%,
	100% {
		transform: scale(1);
		opacity: 0.8;
	}

	50% {
		transform: scale(0.95);
		opacity: 1;
	}
}

/* 🎵 音频波形条 */
.recording-waveform {
	position: absolute;
	bottom: -120rpx;
	display: flex;
	align-items: flex-end;
	justify-content: center;
	gap: 8rpx;
	height: 100rpx;
}

.wave-bar {
	width: 6rpx;
	height: 20rpx;
	background: linear-gradient(to top, #FF5722, #FF7043);
	border-radius: 10rpx;
	animation: waveBarBounce 0.8s ease-in-out infinite;
	animation-delay: var(--bar-delay);
	box-shadow: 0 0 10rpx rgba(255, 87, 34, 0.5);
}

@keyframes waveBarBounce {

	0%,
	100% {
		height: 20rpx;
		opacity: 0.6;
	}

	50% {
		height: 80rpx;
		opacity: 1;
	}
}

/* 📝 提示文字 */
.recording-tip-text {
	position: absolute;
	top: 20rpx;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 20rpx;
	z-index: 2;
}

.recording-status {
	font-size: 28rpx;
	font-weight: bold;
	color: #fff;
	text-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.5);
	letter-spacing: 4rpx;
	animation: textGlow 1.5s ease-in-out infinite;
}

.recording-hint {
	font-size: 24rpx;
	color: rgba(255, 255, 255, 0.7);
	animation: fadeInOut 2s ease-in-out infinite;
}

@keyframes textGlow {

	0%,
	100% {
		text-shadow:
			0 0 20rpx rgba(255, 87, 34, 0.8),
			0 0 40rpx rgba(255, 87, 34, 0.5);
	}

	50% {
		text-shadow:
			0 0 30rpx rgba(255, 87, 34, 1),
			0 0 60rpx rgba(255, 87, 34, 0.7),
			0 0 90rpx rgba(255, 87, 34, 0.4);
	}
}

@keyframes fadeInOut {

	0%,
	100% {
		opacity: 0.5;
	}

	50% {
		opacity: 1;
	}
}

@keyframes countPulse {

	0%,
	100% {
		transform: scale(1);
	}

	50% {
		transform: scale(1.05);
	}
}
</style>